[User]
I'd like to generate some stone walls for a tabletop miniatures game, in 28mm scale. I have a few different variations in mind, so I'm hoping for a parametric approach that lets me easily create variations.

First, I'd like a basic straight wall section. It should be composed of randomly sized and rotated stones, but with a generally rectangular overall shape. The wall should have a defined base of stones that looks distinct from the main wall. I'd like to control the length and height of the wall as parameters. The stones should have a color palette of grays, ranging from light to dark, with the end stones being red.

Secondly, I would like a wall section with a doorway. It should be identical to the basic wall, but with a cylindrical doorway with some additional blocks next to the opening. The positioning of the doorway in the wall is important.

Lastly, I'd also like a circular tower section, composed of multiple wall pieces that create a full tower. I'd want to control the overall size and the number of wall sections in the tower.

I envision each individual stone being a slightly randomized sphere.  I'm not too concerned about a high level of detail, so low poly shapes are fine.

Can you generate OpenSCAD files that can handle these requests, making them parametric so I can easily adjust the scale, dimensions, and number of wall pieces for the circular tower? The colors should be randomly selected from a grayscale palette with red end stones, as described. I am familiar with OpenSCAD and I'd like to keep the code reasonably compact. No need to use any external libraries.

[Assistant]
stonewall.scad:
```

colors = ["Gainsboro", "LightGrey", "Silver", "DarkGray", "Gray",
"DimGray", "LightSlateGray", "SlateGray", "DarkSlateGray", "Black"];
n_colors = 5;

module stone(){ rotate([rands(0, 360, 1)[0],rands(0, 360, 1)[0],rands(0, 360, 1)[0]])resize([rands(3, 10, 1)[0],rands(3, 10, 1)[0],rands(3, 10, 1)[0]])
    //import("rock.stl", convexity=3);
    sphere(1, $fa=15, $fs=1);
    }

module Wall( length, height)
{
    color( colors[rands(0, n_colors-1, 1)[0]])
	scale([0.2,0.2,0.20])
     union() {
    intersection() {

    translate([-34,-22,0]) cube([68,length*40+38,height*20+15 ]) ;

    union() {
        translate([-20,10,0]) cube([40,length*40-20,height*20-5 ]) ;
		// Wall
		for( i = [1:height]) {
			for ( j = [0:length] ) {
				color( colors[rands(0, n_colors-1, 1)[0]])
                        translate([40/2+rands(-5, 5, 1)[0],j*40-(i%2)*10,i*20])
				resize([35,45,35]) stone();
                		translate([-40/2+rands(-5, 5, 1)[0],j*40-(i%2)*10,i*20])
				resize([35,45,35]) stone();
			}
		}

		// Top stones
		for (j = [0:length]) {
				color( colors[rands(0, n_colors-1, 1)[0]])
				translate([rands(-10, 10, 1)[0],j*40+rands(-5, 5, 1)[0],(height+.5)*20])
				resize([40,40,15]) stone();
		}

        	// end stones
		for (j = [0:height]) {
				color("Red")
				translate([0,-5,j*20])
				resize([40,40,40]) stone();
		}
            	// end stones
		for (j = [0:height]) {
				color("Red")
				translate([0,length*40-2,j*20])
				resize([40,40,40]) stone();
		}
	}}
		// Base stones
		difference() {
			scale([1,1,1.5])
			union(){
				for( i = [0:160]) {
					color( colors[rands(0, n_colors-1, 1)[0]])
					translate([rands(-45, 45, 1)[0], rands(0, length*40, 1)[0],rands(0, 15, 1)[0]])
					resize([30,40,20]) stone();
				}
			}

			translate([-240/2,-40, -40])
			cube([240, 80+40*length+20, 40]);
		}
	}
}

//translate([-50,0,0])Wall(5, 15);
difference(){
Wall(10, 10);}
cylinder(10[1,0,0]);

  //cube([28,28,28]);

//translate([0, 10*40+50, 0])
//rotate([0,0,-30])
//Wall(5, 10);
```
stonewalldoor.scad:
```

colors = ["Gainsboro", "LightGrey", "Silver", "DarkGray", "Gray",
"DimGray", "LightSlateGray", "SlateGray", "DarkSlateGray", "Black"];
n_colors = 5;

module stone(){ rotate([rands(0, 360, 1)[0],rands(0, 360, 1)[0],rands(0, 360, 1)[0]])resize([rands(3, 10, 1)[0],rands(3, 10, 1)[0],rands(3, 10, 1)[0]])
    //import("rock.stl", convexity=3);
    sphere(1, $fa=15, $fs=1);
    }

module Wall( length, height)
{
    color( colors[rands(0, n_colors-1, 1)[0]])
	scale([0.2,0.2,0.20])
     union() {
    intersection() {

    translate([-34,-22,0]) cube([68,length*40+38,height*20+15 ]) ;

    union() {
        translate([-20,10,0]) cube([40,length*40-20,height*20-5 ]) ;
		// Wall
		for( i = [1:height]) {
			for ( j = [0:length] ) {
				color( colors[rands(0, n_colors-1, 1)[0]])
                        translate([40/2+rands(-5, 5, 1)[0],j*40-(i%2)*10,i*20])
				resize([35,45,35]) stone();
                		translate([-40/2+rands(-5, 5, 1)[0],j*40-(i%2)*10,i*20])
				resize([35,45,35]) stone();
			}
		}

		// Top stones
		for (j = [0:length]) {
				color( colors[rands(0, n_colors-1, 1)[0]])
				translate([rands(-10, 10, 1)[0],j*40+rands(-5, 5, 1)[0],(height+.5)*20])
				resize([40,40,15]) stone();
		}

        	// end stones
		for (j = [0:height]) {
				color("Red")
				translate([0,-5,j*20])
				resize([40,40,40]) stone();
		}
            	// end stones
		for (j = [0:height]) {
				color("Red")
				translate([0,length*40-2,j*20])
				resize([40,40,40]) stone();
		}
	}}
		// Base stones
		difference() {
			scale([1,1,1.5])
			union(){
				for( i = [0:160]) {
					color( colors[rands(0, n_colors-1, 1)[0]])
					translate([rands(-45, 45, 1)[0], rands(0, length*40, 1)[0],rands(0, 15, 1)[0]])
					resize([30,40,20]) stone();
				}
			}

			translate([-240/2,-40, -40])
			cube([240, 80+40*length+20, 40]);
		}
	}
}

//translate([-50,0,0])Wall(5, 15);
difference(){
Wall(10, 10);
translate([0,40,25])rotate ([0,90,0]) cylinder (h = 80, r=11, center = true, $fn=10);
    translate([0,40,010]) cube ( [30,21,33], center = true, $fn=10);

    }

  //cube([28,28,28]);

//translate([0, 10*40+50, 0])
//rotate([0,0,-30])
//Wall(5, 10);
```
stonewalltowerA.scad:
```

colors = ["Gainsboro", "LightGrey", "Silver", "DarkGray", "Gray",
"DimGray", "LightSlateGray", "SlateGray", "DarkSlateGray", "Black"];
n_colors = 5;

module stone(){ rotate([rands(0, 360, 1)[0],rands(0, 360, 1)[0],rands(0, 360, 1)[0]])resize([rands(3, 10, 1)[0],rands(3, 10, 1)[0],rands(3, 10, 1)[0]])
    //import("rock.stl", convexity=3);
    sphere(1, $fa=15, $fs=1);
    }

module Wall( length, height)
{
    color( colors[rands(0, n_colors-1, 1)[0]])
	scale([0.2,0.2,0.20])
     union() {
    intersection() {

    translate([-34,-22,0]) cube([68,length*40+38,height*20+15 ]) ;

    union() {
        translate([-20,10,0]) cube([40,length*40-20,height*20-5 ]) ;
		// Wall
		for( i = [1:height]) {
			for ( j = [0:length] ) {
				color( colors[rands(0, n_colors-1, 1)[0]])
                        translate([40/2+rands(-5, 5, 1)[0],j*40-(i%2)*10,i*20])
				resize([35,45,35]) stone();
                		translate([-40/2+rands(-5, 5, 1)[0],j*40-(i%2)*10,i*20])
				resize([35,45,35]) stone();
			}
		}

		// Top stones
		for (j = [0:length]) {
				color( colors[rands(0, n_colors-1, 1)[0]])
				translate([rands(-10, 10, 1)[0],j*40+rands(-5, 5, 1)[0],(height+.5)*20])
				resize([40,40,15]) stone();
		}

        	// end stones
		for (j = [0:height]) {
				color("Red")
				translate([0,-5,j*20])
				resize([40,40,40]) stone();
		}
            	// end stones
		for (j = [0:height]) {
				color("Red")
				translate([0,length*40-2,j*20])
				resize([40,40,40]) stone();
		}
	}}
		// Base stones
		difference() {
			scale([1,1,1.5])
			union(){
				for( i = [0:160]) {
					color( colors[rands(0, n_colors-1, 1)[0]])
					translate([rands(-45, 45, 1)[0], rands(0, length*40, 1)[0],rands(0, 15, 1)[0]])
					resize([30,40,20]) stone();
				}
			}

			translate([-240/2,-40, -40])
			cube([240, 80+40*length+20, 40]);
		}
	}
}

union(){
for( i = [0:5]) {
rotate ([0,0,45*i]) translate ([50,-21,0]) Wall(5,25);

}}
```
stonewell.scad:
```

colors = ["Gainsboro", "LightGrey", "Silver", "DarkGray", "Gray",
"DimGray", "LightSlateGray", "SlateGray", "DarkSlateGray", "Black"];
n_colors = 5;

module stone(){ rotate([rands(0, 360, 1)[0],rands(0, 360, 1)[0],rands(0, 360, 1)[0]])resize([rands(3, 10, 1)[0],rands(3, 10, 1)[0],rands(3, 10, 1)[0]])
    //import("rock.stl", convexity=3);
    sphere(1, $fa=15, $fs=1);
    }

module Wall( length, height)
{
    color( colors[rands(0, n_colors-1, 1)[0]])
	scale([0.2,0.2,0.20])
     union() {
    intersection() {

    translate([-29,-22,0]) cube([63,length*40+44,height*20+17 ]) ;

    union() {
        translate([-8,10,0]) cube([20,length*40-25,height*20-5 ]) ;
		// Wall
		for( i = [1:height]) {
			for ( j = [0:length] ) {
				color( colors[rands(0, n_colors-1, 1)[0]])
                        translate([40/2+rands(-5, 5, 1)[0],j*40-(i%2)*10,i*20])
				resize([35,45,35]) stone();
                		translate([-40/2+rands(-5, 5, 1)[0],j*40-(i%2)*10,i*20])				resize([35,45,35]) stone();
			}
		}

		// Top stones
		for (j = [0:length]) {
				color( colors[rands(0, n_colors-1, 1)[0]])
				translate([rands(-10, 10, 1)[0],j*40+rands(-5, 5, 1)[0],(height+.5)*20])
				resize([40,40,15]) stone();
		}

        	// end stones
		for (j = [0:height]) {
				color("Red")
				translate([0,-5,j*20])
				resize([40,40,40]) stone();
		}
            	// end stones
		for (j = [0:height]) {
				color("Red")
				translate([0,length*40-2,j*20])
				resize([40,40,40]) stone();
		}
	}}
		// Base stones
		difference() {
			scale([1,1,1.5])
			union(){
				for( i = [0:160]) {
					color( colors[rands(0, n_colors-1, 1)[0]])
					translate([rands(0, 45, 1)[0], rands(0, length*40, 1)[0],rands(0, 15, 1)[0]])					resize([30,40,20]) stone();
				}
			}

			translate([-240/2,-40, -40])			cube([240, 80+40*length+20, 40]);
		}
	}
}

union(){
for( i = [0:7]) {
rotate ([0,0,45*i]) translate ([22,-8,0]) Wall(2,6);

}}
```


[User]
Hey, I'm looking for some help designing a parametric pole clamp in OpenSCAD. I've got some wildlife cameras I'd like to mount on the same pole that my bird feeders hang from, and I need a way to attach a horizontal pole to a vertical one.

Here's what I'm envisioning:

The design should be a two-part clamp that hinges together and is secured with a screw and nut. The main part of the clamp will have a circular cutout to fit around the vertical pole. I also want a second pole extending outwards, perpendicular from the main clamp. I want to control several parameters.

**Parameters:**

*   `clamp_height`: The height of the main clamp body.
*   `clamp_pole_diam`: The diameter of the vertical pole being clamped.
*   `screw_hole_diam`: The diameter of the screw holes for fastening the two halves.
*   `screw_recess_diam`: The diameter of the recess for the screw head and nut.
*   `nut_type`: An integer that controls the nut shape (4 for square, 6 for hex).
*   `pole2_diam`: The diameter of the horizontal pole.
*   `pole2_angle`: The angle of the horizontal pole relative to the vertical pole (I'd like this to be able to be non-perpendicular - maybe something like 135 degrees or so).

**Features:**

*   The two halves of the clamp should connect via a simple hinge mechanism. I don't need anything too fancy - I'm thinking of something like a few vertical pin hinges.
*   The clamp should have recesses for both the screw head and the nut on the same side. The screw should pass through both halves, but the nut and screw head should be on the same side.
*   The horizontal pole should be an integral part of the clamp, not something I have to add separately.
*   I'd like to use the BOSL library for the nut/bolt features. Specifically I will be using the `metric_bolt()` module and would like it if the screw head recess automatically adjusts to its shape and size.

I think that covers it. Let me know if you have any questions. I'm really excited to see what you come up with!

[Assistant]
parametric_pole_clamp.scad:
```
$fn = 0;

$fs = 0.1; // HQ cylinders
$fa = 4; // HQ spheres/hulls
render_hinges = true;

//$fs = 2; // default
//$fa = 12; // default
//render_hinges = false;

clamp_height = 30;
clamp_pole_diam = 25;

screw_hole_diam = 4.5;
screw_recess_diam = 9;
nut_type = 6; // 4=square, 6=hex

pole2_diam = 13;
pole2_angle = 135;

horiz_pole_diam = pole2_diam;

pole_diam = clamp_pole_diam;

hinged_pole_clamp(
  height=clamp_height,
  hole_diam=screw_hole_diam,
  hole_recess_diam=screw_recess_diam,
  horiz_diam=horiz_pole_diam,
  nut_type=nut_type,
  pole_diam=pole_diam);

module hinged_pole_clamp(
    height,
    hole_diam,
    pole_diam,
    hole_recess_diam,
    horiz_diam,
    horiz_tab_angle=40,
    horiz_thick=3,
    nut_type=6
){
  hinge_fill_x = 23.6; //hardcoded to fit the hinge footprint
  hinge_fill_y = 20;
  hinge_fill_z = height;
  hole_r = hole_diam/2;
  pole_r = pole_diam/2;
  hole_recess_r = hole_recess_diam/2;

  hpole_r = horiz_diam/2;

  half_space = 0.5; // gap between the two halfs
  half_width = pole_diam * 1.2;
  half_depth = pole_diam * 0.6;

  flap_width = 1;
  flap_height = hole_recess_diam*1.5;

  hinge_r1 = 5;
  num_hinges = clamp_height/(hinge_r1*2) - 1;

  difference (){

    union(){

      //one half
      hull(){
        translate([
            hinge_fill_x,
            0-(half_depth-((hinge_fill_y+half_space)/2)),
            0])
            cube(size=[half_width*0.8, half_depth, hinge_fill_z]);

        translate([
            hinge_fill_x+(half_width*0.8),
            (0-(half_depth-((hinge_fill_y+half_space)/2)))+half_depth-flap_width,
            0])
            cube(size=[
              (half_width*0.2)+(hole_recess_diam*1.5),
              flap_width,
              hinge_fill_z
            ]);

      }

      difference(){
          translate([
            hinge_fill_x,
            0-(half_depth-((hinge_fill_y+half_space)/2)),
            0])
          h_pole(
            half_width,
            half_depth,
            hinge_fill_z,
            hpole_r,
            horiz_thick,
            tab_angle=horiz_tab_angle,
            hole_diam=screw_hole_diam,
            hole_recess_diam=screw_recess_diam,
            nut_type=nut_type,
            h_angle=pole2_angle
          );
      }
      //hinge fill
      translate([0, 0, 0])
          cube(size=[hinge_fill_x, hinge_fill_y+half_space, hinge_fill_z]);

      //the other half
      hull(){
        translate([
          hinge_fill_x, (0-(half_depth-((hinge_fill_y+half_space)/2)))+half_depth+half_space,
          0
        ])
          cube(size=[half_width*0.8, half_depth, hinge_fill_z]);

        translate([
          hinge_fill_x+(half_width*0.8),
          (0-(half_depth-((hinge_fill_y+half_space)/2)))+half_depth+half_space,
          0
        ])
          cube(size=[
            (half_width*0.2)+(hole_recess_diam*1.5),
            flap_width,
            hinge_fill_z
          ]);
      }
    }

    translate([
        hinge_fill_x+(half_width*1)+(hole_recess_diam*0.75),

        (0-(half_depth-((hinge_fill_y+half_space)/2)))+half_depth+half_space,
        height/2]){

      rotate(a=90, v=[1,0,0]){
        cylinder(h=pole_diam*1.5, r=hole_r, center=true);

        translate([0,0,0+(half_depth/2)+3])
          cylinder(h=half_depth, r=hole_recess_r, center=true, $fn=nut_type);

        translate([0,0,0-(half_depth/2)-3])
          cylinder(h=half_depth, r=hole_recess_r, center=true);
      }
    }

    //pole hole
    translate([hinge_fill_x+(half_width/2), (hinge_fill_y+half_space)/2, -(((height*1.1)-hinge_fill_z)/2)]) {
      rotate(a=90, v=[0,0,0])
        cylinder(h=(height*1.1), r=pole_r);
    }

    //hinges
    if(render_hinges)
      translate([10, (hinge_fill_y+(half_space*2))/2 ,0])
        rotate(a=(-45/2), v=[0,0,1])
          vertical_hinge_negative(theta0=45, height=(hinge_fill_z/num_hinges), n=num_hinges, r1=hinge_r1);

  }
}

/*
* tol - the smallest distance allowable between interlocking parts of your 3d printer. This gap is the
vertical (and horizontal) distance between the cones inside the hinge and is also the diameter and height of the
small support structure between hinge elements
* r1 - the outer radius of the hinge. the surface of your part should not be farther away from the center of
the hinge than this disntace.
* r2 - the furthest radius from the hinge where material is removed from the part.
* height - the height of each hinge element. The total height of the hinge is n*height. (the cut will extent
beyond this distance by height/2 on both sides. The part where you are creating the hinge should have a height
of n*height) the height must be greater than 2*r1
* n - the number of hinge elements. One hinge element is divided between the top and bottom.
* theta0 - the angle at which the hinge is printed
* theta1 - the internal angle formed when the hinge is turned to its limit in one direction (the x- part of the
hinge_test_1 example when rotated clockwise as viewed from above)
* theta2 - the internal angle formed when the hinge is turned to its limit in the opposite direction
*/
module vertical_hinge_negative(tol=0.5,r1=5,r2=15,height=15,n=2,theta0=180,theta1=45,theta2=45) {

    arm_width=2*r1;
    union() {
        for(i=[0:n])
            translate([0,0,(i-0.5)*height])
                difference() {

                    //cone between hinges and cuts around the hinge
                    rotate_extrude()
                        polygon([[r1,0],[r1,height],[tol/2,height-r1+tol/2],
                                [tol/2,height-r1+1.5*tol],[r1,height+tol],
                                [r2,height+tol],[r2,0]]);

                    //exclude a rectangular shape for the arm the connects the hinge to the body
                    rotate((i%2)*theta0)
                        difference() {
                            translate([0,-arm_width/2,-height])
                                cube(size=[r2*2,arm_width,height*2]);

                            translate([0,0,height-r1])
                                cylinder(r1=0,r2=height,h=height);
                        }

                    //exclude a triangular shape that limits the motion of the arms on the side of the hinge
                    for(i=[0,1])
                        mirror([0,i,0])
                            rotate(-i*theta0)
                                translate([0,0,-tol])
                                    linear_extrude(height=height+3*tol)
                                        intersection() {
                                            circle(r=2*r2);

                                            rotate(theta0+180+theta2)
                                                translate([0,r2*3+arm_width/2+tol])
                                                    square(size=[r2*6,r2*6],center=true);

                                            rotate(theta0-theta1)
                                                translate([0,r2*3+arm_width/2+tol])
                                                    square(size=[r2*6,r2*6],center=true);

                                            rotate(theta0)
                                                translate([r2*3,0])
                                                    square(size=[r2*6,r2*6],center=true);
                                        }
            }
       }
}

//*********************************************************

module h_pole(width, depth, height, pole_r, pole_thick, tab_angle, hole_diam, hole_recess_diam, nut_type=4, h_angle=90
){
    hole_r = hole_diam/2;

    neg_tab = height;
    neg_tab_w = 1;
    tab_h = (pole_r + pole_thick + hole_recess_diam) + 1;
    tab_d = 4;
    tab_w = hole_recess_diam;

    angle = h_angle;

    difference(){
        union(){
            hull(){
                cube(size=[width*0.8, depth, height]);
                translate([(width*0.8)/2, 0-(pole_r+pole_thick), height/2])
                rotate([0, angle, 0])
                cylinder(h=width*0.8, r=pole_r+pole_thick, center=true);
            }
            hull(){
                translate([(width*0.8)/2, 0-(pole_r+pole_thick), height/2]){
                    rotate([0, angle, 0]){
                        cylinder(h=width*0.8, r=pole_r+pole_thick, center=true);

                        rotate([0, 0, tab_angle])
                        translate([0-(tab_h), 0-(tab_d/2), 0-(tab_w/2)])
                        cube([tab_h, tab_d, tab_w], center=false);
                    }
                }
            }
        }
        translate([(width*0.8)/2, 0-(pole_r+pole_thick), height/2]){
            rotate([0, angle, 0]){
                cylinder(h=width*2, r=pole_r, center=true);

                rotate([0, 0, tab_angle])
                translate([0-(neg_tab), 0-(neg_tab_w/2), 0-(width)])
                cube([neg_tab, neg_tab_w, width*2], center=false);

                rotate([90, 0, tab_angle])
                translate([0-pole_r-(pole_thick)-(hole_recess_diam/2), 0, 0]){
                    cylinder(h=pole_r*3, r=hole_r, center=true);

                    translate([0, 0, ((pole_r*3)/2)+(neg_tab_w/2)+neg_tab_w])
                    cylinder(h=pole_r*3, r=hole_recess_diam/2, center=true);

                    translate([0, 0, 0-((pole_r*3)/2)-(neg_tab_w/2)-neg_tab_w])
                    cylinder(h=pole_r*3, r=hole_recess_diam/2, center=true, $fn=nut_type);
                }
            }
        }
    }
}

```


[User]
I'd like to create a parametric PCB holder and standoff generator in OpenSCAD. I need to be able to switch between generating either a holder with grooves for the board edges or a standoff with mounting points for the board.

For the PCB dimensions, I need to specify the length (X) and width (Y), with the width always being less than or equal to the length. There should also be a base width and height parameter.

If I select the "holder" style, I need to specify the clearance between the PCB and the base, along with the PCB groove thickness. The design should have cylinders in each corner that act as guides or supports, with a cutout to insert the PCB.

If I select the "standoff" style, I want to select between round, square, or hex stand shapes, and either male or female mounting styles. The height of the stand portion should also be configurable, along with the diameter of the mounting holes and the height of those holes (or mount cylinders).

It should also calculate the radius and center of an arc, the distance from the edge of the polygon, a cylinder diameter and height, and the height of the stand. Also, the width of a cube.

The base should be created from two arcs that are mirrored with a polygon that connects them. If pcb_x equals pcb_y, then a box should be generated. If it is the "holder" style, then a difference will subtract the pcb from the holders. A linear extrude of a polygon will also be subtracted in all four corners. If the style is set to stand, then the stand module will be called.

Here are the parameters I need:

**Global:**
*   `style`:  Integer, either 1 for "PCB Holder" or 2 for "PCB Standoff".
*   `pcb_X`: PCB length.
*   `pcb_Y`: PCB width (<= pcb_X).
*   `base_width`: Width of the base.
*  `base_height`: Height of the base.

**Holder:**
*   `pcb_clearance`: Distance between the PCB and the base.
*   `pcb_thickness`:  PCB groove height.

**Standoff:**
*   `stand_shape`: Integer, 1 for "Round", 2 for "Square", or 3 for "Hex" edges.
*   `stand_style`: Integer, 1 for "Male", 2 for "Female" mounting style.
*   `stand_extend`: Height of the stand portion.
*   `hole_diameter`: Diameter of PCB holes.
*  `hole_height`: Height of the hole (female) or mount cylinder (male).

**Hidden:**
*   `cyl_top`: a small height to add to the cutouts of the holder type.
*  `debug`: 0 or 1 for debugging (not necessary for the final output)

It would be awesome if you could handle all of the necessary calculations internally. I'm really looking for a fully parametric design. I don't need any libraries and I'd like to keep the code as simple as possible while staying readable.

[Assistant]
pcb_holder.scad:
```
/* [Global] */
style = 2; // [1:PCB Holder, 2:PCB Standoff]
//length of the PCB or holes distance
pcb_X = 85;
//width of the PCB or holes distance (width cannot be greater than length)
pcb_Y = 54;
base_width = 8;
base_height = 2;

/* [Holder] */
//distance between PCB and base
pcb_clearance = 2;
//pcb groove height
pcb_thickness = 1.8;

/* [Standoff] */
//select the shape of the 4 edges
stand_shape = 1; // [1:Round, 2:Square, 3:Hex]
//select the mounting style
stand_style = 1; //[1:Male, 2:Female]
//height of 4 edges
stand_extend = 10;
//diameter of hole PCB hole
hole_diameter = 3;
//height of hole(female) or mount cylinders(male)
hole_height = 12;

/* [Hidden] */
cyl_top = 2;
debug = 0;
$fn = 100;

//caclulations
pcb_center_X = pcb_X/2;
pcb_center_Y = pcb_Y/2;
arc_R = (pow(pcb_center_X,2) + pow(pcb_center_Y,2)) / (2*pcb_center_Y) + base_width/2;
arc_center_x = pcb_center_X;
arc_center_y = - (arc_R - pcb_center_Y) + base_width/2;
poly_edge_dist = (pcb_center_X * pcb_center_Y) / (arc_R-base_width/2 - pcb_center_Y);
cyl_D = base_width ;
cyl_height = base_height + pcb_clearance + pcb_thickness + cyl_top;
stands_height = stand_extend + base_height;
cube_w = sqrt(pow(base_width,2)/2);

if (style == 1){
	base();
}
else{
	if (stand_style == 1){ //male stand
		union(){
			base();
			translate([0,0,stands_height]) cylinder (d=hole_diameter, h=hole_height);
			translate([pcb_X,0,stands_height]) cylinder (d=hole_diameter, h=hole_height);
			translate([pcb_X,pcb_Y,stands_height]) cylinder (d=hole_diameter, h=hole_height);
			translate([0,pcb_Y,stands_height]) cylinder (d=hole_diameter, h=hole_height);
		}
	}
	else{ //female stand
		difference(){
			base();
			translate([0,0,stands_height-hole_height]) cylinder (d=hole_diameter, h=hole_height);
			translate([pcb_X,0,stands_height-hole_height]) cylinder (d=hole_diameter, h=hole_height);
			translate([pcb_X,pcb_Y,stands_height-hole_height]) cylinder (d=hole_diameter, h=hole_height);
			translate([0,pcb_Y,stands_height-hole_height]) cylinder (d=hole_diameter, h=hole_height);
		}
	}
}

module base(){
	if (!(pcb_X < pcb_Y)){
		intersection(){
			union(){
				arc();
				translate([0, 2*arc_R-base_width, 0]) arc();
			}
			if (pcb_X!=pcb_Y){
				linear_extrude(height = base_height) polygon([[0,0],[arc_center_x,arc_center_y],[pcb_X,0],[pcb_X+poly_edge_dist,pcb_center_Y],[arc_center_x,arc_R+pcb_center_Y-base_width/2],[0,pcb_Y],[-poly_edge_dist,pcb_center_Y]]);
			}
			else{
				translate([-base_width/2, 0, 0]) cube([pcb_X+base_width,pcb_Y,base_height]);
			}
		}
	}
	if (style == 1){ //pcb holder
		difference(){
			holders();
			translate([0,0,base_height+pcb_clearance]) cube([pcb_X, pcb_Y, pcb_thickness]);
			translate([0,0,base_height+pcb_clearance]) linear_extrude(height = pcb_thickness+cyl_top+1) polygon([[0,cyl_D/2],[cyl_D/2,cyl_D/2],[cyl_D/2,0]]);
			translate([pcb_X,0,base_height+pcb_clearance]) rotate([0,0, 90]) linear_extrude(height = pcb_thickness+cyl_top+1) polygon([[0,cyl_D/2],[cyl_D/2,cyl_D/2],[cyl_D/2,0]]);
			translate([pcb_X,pcb_Y,base_height+pcb_clearance]) rotate([0,0, 180]) linear_extrude(height = pcb_thickness+cyl_top+1) polygon([[0,cyl_D/2],[cyl_D/2,cyl_D/2],[cyl_D/2,0]]);
			translate([0,pcb_Y,base_height+pcb_clearance]) rotate([0,0, 270]) linear_extrude(height = pcb_thickness+cyl_top+1) polygon([[0,cyl_D/2],[cyl_D/2,cyl_D/2],[cyl_D/2,0]]);
		}
	}
	else{ //pcb stand
		stands();
	}
}

module arc () {
	difference(){
		translate([arc_center_x, arc_center_y, 0]) cylinder (r=arc_R, h=base_height);
		translate([arc_center_x, arc_center_y, -1]) cylinder (r=arc_R - base_width, h=base_height+2);
	}
}

module holders(){
	union(){
			cylinder (d=cyl_D, h=cyl_height);
			translate([0, pcb_Y, 0]) cylinder (d=cyl_D, h=cyl_height);
			translate([pcb_X, pcb_Y, 0]) cylinder (d=cyl_D, h=cyl_height);
			translate([pcb_X, 0, 0]) cylinder (d=cyl_D, h=cyl_height);
		}
}

module stands(){
	if (stand_shape == 1){ //round tops
		cylinder (d=cyl_D, h=stands_height);
		translate([0, pcb_Y, 0]) cylinder (d=cyl_D, h=stands_height);
		translate([pcb_X, pcb_Y, 0]) cylinder (d=cyl_D, h=stands_height);
		translate([pcb_X, 0, 0]) cylinder (d=cyl_D, h=stands_height);
	}
	else if (stand_shape == 2){ //square tops
		translate([0, 0, stand_extend/2+base_height/2]) rotate([0,0,45+atan(arc_center_y/arc_center_x)]) cube([cube_w,cube_w,stands_height], true);
		translate([0, pcb_Y, stand_extend/2+base_height/2]) rotate([0,0,45+atan(arc_center_x/arc_center_y)]) cube([cube_w,cube_w,stands_height], true);
		translate([pcb_X, pcb_Y, stand_extend/2+base_height/2]) rotate([0,0,45+atan(arc_center_y/arc_center_x)]) cube([cube_w,cube_w,stands_height], true);
		translate([pcb_X, 0, stand_extend/2+base_height/2]) rotate([0,0,45+atan(arc_center_x/arc_center_y)]) cube([cube_w,cube_w,stands_height], true);
	}
	else{ //hex tops
		rotate([0,0,atan(arc_center_y/arc_center_x)]) cylinder (d=cyl_D, h=stands_height, $fn = 6);
		translate([0, pcb_Y, 0]) rotate([0,0,90+atan(arc_center_x/arc_center_y)]) cylinder (d=cyl_D, h=stands_height, $fn = 6);
		translate([pcb_X, pcb_Y, 0]) rotate([0,0,atan(arc_center_y/arc_center_x)]) cylinder (d=cyl_D, h=stands_height, $fn = 6);
		translate([pcb_X, 0, 0]) rotate([0,0,90+atan(arc_center_x/arc_center_y)]) cylinder (d=cyl_D, h=stands_height, $fn = 6);
	}
}

if (debug){
	#translate([arc_center_x, arc_center_y, 0]) cylinder (d=5, h=10);
	#translate([arc_center_x, arc_R+pcb_center_Y-base_width/2, 0]) cylinder (d=5, h=10);
}

```


[User]
Hey, I'm looking to design a filament storage system for my 3D printer, and I'd like it to be based on the design I've been using that's been modified to accommodate roller wheels. I'm not terribly attached to the specific dimensions, as it'll need to fit in an Ikea Samla box, but there are some key components I need, and I want to make it parametric.

Basically, it consists of two main parts: supports that hold two 8mm steel rods, and roller wheels that sit on those rods for the filament spools to roll on. I'm looking for an OpenSCAD file that allows me to control all of the important dimensions.

For the supports, I need to be able to adjust the dimensions, specifically the width, length, and height of the base cube, and the placement of the two rod holders. The rod holders themselves need to have some slack for the 8mm rods, and I also want to be able to control how much the support sticks out from the wall, as there are cutouts that also should have a similar slack value. I want to specify an overall base shape and a single "holder" shape, and be able to mirror it on either side as appropriate.

For the rollers, I need a wheel shape, where I can control its overall diameter, the depth and width of the groove that will hold the filament spool, the side width, and the slack around the 8mm rod they rotate on. I’d also like to be able to easily output single rollers, two rollers next to each other, and a 2x2 grid of rollers so I can print out the right number I need.

Essentially, I'm looking for something that allows me to tweak all these dimensions, so I can adjust it to work perfectly inside my box and print the appropriate number of rollers I need. I don't need anything particularly fancy here, just the basic functionality for now. Can you help with that?

[Assistant]
filament-storage.scad:
```
// -------------------------------------------------------------------------------------------------

// Filament Storage, Quick Change - with two 8mm steel rods in Ikea Samla box
// © anton@cking.be
//   https://www.youmagine.com/users/ant0ni0
//   https://www.thingiverse.com/ant0ni0

// GLOBAL PARAMETERS -------------------------------------------------------------------------------

/* [Dimensions] */

rd = 8.0;  // rod diameter
ss = 0.6;  // support slack
rs = 1.2;  // roller slack
gd = 2.2;  // groove depth
sw = 1.3;  // side width
gw = 4.0;  // groove width

od = 22.0; // overall diameter

/* [Hidden] */

$fa = 0.5; // minimum facet angle
$fs = 0.5; // minimum facet size

// BUILD -------------------------------------------------------------------------------------------

display();
//roller();
//2rollers();
//4rollers();
//support();

// MODULES -----------------------------------------------------------------------------------------

module display()
{
    for (f=[0,1])
        translate([f*290,0,0]) rotate([0,-90,f*180]) support();

    for (y=[-52,52])
        translate([-5,y,30]) rotate([0,90,0]) %cylinder(d=rd,h=300);

    // TODO add some rollers
}

module roller()
{
    difference()
    {
        union()
        {
            cylinder(d=od,h=sw);
            translate([0,0,sw]) cylinder(d1=od,d2=od-2*gd,h=gd);
            translate([0,0,sw+gd]) cylinder(d=od-2*gd,h=gw);
            translate([0,0,sw+gd+gw]) cylinder(d1=od-2*gd,d2=od,h=gd);
            translate([0,0,sw+2*gd+gw]) cylinder(d=od,h=sw);
        }

        translate([0,0,-1]) cylinder(d=rd+rs,h=99);
    }
}

module 2rollers()
{
    for (x=[0,od+2])
        translate([x,0,0]) roller();
}

module 4rollers()
{
    for (x=[0,od+2])
        for (y=[0,od+2])
            translate([x,y,0]) roller();
}

module support()
{
    difference()
    {
        translate([0,-64,0]) cube([40,128,40]);

        for (m=[0,1])
        {
            mirror([0,m,0])
            {
                translate([0,0,20]) rotate([4,86,0]) translate([4,0,-10])
                union()
                {
                    translate([0,49,0]) cylinder(d=24,h=80);
                    translate([-12,-10,0]) cube([24,59,80]);
                    translate([-12,49]) cube([12,12,80]);
                    translate([-24,0,0]) cube([20,80,80]);
                    //translate([-4,61,0]) rotate([0,0,45]) translate([-0.6,-0.6,0]) cube([1.2,1.2,80]);
                }
            }
        }

        for (f=[-1,1])
        {
            translate([30,f*52,-1]) cylinder(d=rd+ss,h=6);
            translate([0,f*74-10,0]) rotate([0,0,-f*4]) translate([-10,0,-1]) cube([60,20,30]);
        }

        hull()
        {
            for (y=[-32,32])
                translate([12,y,-1]) cylinder(d=18,h=10);
            translate([-2,-44,-1]) cube([1,88,10]);
        }
    }
}

// -------------------------------------------------------------------------------------------------

```


[User]
I want to design a customizable enclosure for a RAMPS 1.4 board, but I need it to be a bit more flexible than the ones I've found online. I'm thinking something like a parametric box, with the option to print just the base, just the lid, or both together.

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

*   **Part Selection:** I need a variable to choose which part(s) to render: just the box, just the lid, or both.
*   **Resolution:** I want to control the roundness of circles and curves with a variable that defines the length of each line segment. Smaller values should mean higher resolution, but take longer to render.
*   **Extrusion Width:** I need a variable to set the single wall extrusion width based on my nozzle size. This will be the basis for all wall thicknesses.
*   **Box Height:** A variable to set the overall height of the box.
*   **Mounting Options:** A variable to choose between no mounting holes or 4 mounting holes on the bottom, spaced 30x60 and centered.
*   **Smart Adapter:** A boolean variable to add extra space for a RepRap Discount Full Graphic Smart Controller adapter.
*   **Top Fan:** A boolean variable to add a fan hole and mounting holes in the lid.
*   **Back Style:** A variable to select different back panel styles: open, with a fan mount, or closed.
*   **Reset Button:** A boolean to add an accessible reset button with a push button on the box.
*   **Extra Space:** Variables to control extra space around the board in all four directions (front, back, left, right).
*   **Wall Thickness:** Separate variables to control the extrusion factor for the lid, bottom, front, back, left, right, corners, and board mounts. These factors would be multiplied by the single wall extrusion width.
*   **Over-deposition:** A variable to compensate for over-deposition of the 3D printer, mostly when printing holes.
*   **Board Spacing:** A variable to control the spacing between the bottom of the box and the RAMPS board.
*   **Bridge Height:** A variable to control a bridge height between the front and back of the box. Should match my fan height if I choose to add one to the lid.
*   **Screw Dimensions:** Variables for the diameter and length of the self-tapping screws to mount the board and the lid.
*   **Fan Dimensions:** Variables for the fan diameter and mounting hole diameter, and also the offset of the mounting holes from the fan center.

I also need a few internal dimensions defined as variables:

*   The dimensions of the RAMPS board (x,y,z)
*   The internal diameter of an M3 screw
*   Calculated radii for screws
*   A few booleans based on the settings, like whether there is a back fan or a back opening
*   Variables to calculate various thicknesses (based on the extrusion factor and single wall thickness)
*   A variable for the board's y dimension, taking into account a smart adapter if one is selected.
*   A variable for how far the back opening extends

I'm also interested in being able to add mounting for some Knight aluminum extrusions for a specific printer that I use, but this could be optional or skipped for now if needed, though the variable names for this already exist. Let me know if you need more details about this part.

I want to ensure that the design is fully parametric so I can easily adjust it later if I need to make changes for different hardware revisions. I do not want any .stl file to be generated, and the output should be the .scad files only.

I'm hoping to have these generated as a single .scad file, but I understand if you need to split it into more than one. I don't have any strong preference as long as they work together. I'd prefer that the functions be grouped together separately from the modules.

I don't need any external libraries for this.

[Assistant]
ramps_14_box.scad:
```
/*
Name: RAMPS 1.4 box in OpenSCAD
Author: Jons Collasius from Germany/Hamburg

License: CC BY-NC-SA 4.0
License URL: https://creativecommons.org/licenses/by-nc-sa/4.0/
*/

/* [Global] */
// ######## global variables ########

// what part to print
part = 3; // [1:print just the box,2:print just the lid,3:print the box and the lid]
// resolution of round object. each line segment is fnr mm long. fnr = 1 crude and good for development (its faster), aim for fnr = 0.4 or smaller for a production render. smaller means more detail (and a lot more time to render).
resolution = 0.4;
// extrusion thicknesses of your nozzle
single_wall 		= 0.6;
// hight of the box (65 is a fair choice, ad some mm if you want to mount the top fan inside the case)
box_hight = 65;
// mount type
mount_type = 0; // [0:without any mount holes,1:4 bottom mounts holes - spaced 30*60 and centered]
// extend the box for the RepRap Discount Full Graphic Smart Controller adapter
smartadapter			= false; // [true:YES box with xtra space for the smart adapter,false:NO without smart adapter]
// add a fan hole and mounts in the lid
topfan					= true;	// [true:YES with top fan,false:NO without top fan]
// style of the back side, open, closed or with fan mount
backstyle = 2; // [1:open,2:with fan hole and mounts,3:closed]
// make the reset button accessible and add a push button
resetbutton				= true;	//[true:YES with reset button,false:NO without reset button]
// extra space in front of the board
ramps_xtra_front         = 0;
// extra space behind the board (maybe for a fan, mounted inside the case?)
ramps_xtra_back         = 0;
// extra space left of the board
ramps_xtra_left         = 0;
// extra space right of the board
ramps_xtra_right         = 0;
// extrusion factor of the thickness of the lid (single_wall * X)
factor_lid 			= 3;
// extrusion factor of the thickness of the bottom (single_wall * X)
factor_bottom 		= 3;
// extrusion factor of the thickness of the front wall (single_wall * X)
factor_front 		= 3;
// extrusion factor of the thickness of the back wall (single_wall * X)
factor_back 		= 3;
// extrusion factor of the thickness of the left wall (single_wall * X)
factor_left 		= 3;
// extrusion factor of the thickness of the right wall (single_wall * X)
factor_right 		= 3;
// extrusion factor of the thickness of the corners (single_wall * X)
factor_corners 		= 3;
// extrusion factor of the thickness of the boardmounts (single_wall * X)
factor_boardmounts 	= 3;
// overdepositing of your 3d printer (if prining a hole, how much to enlarge the hole for perfect fit). leave at 0 if you don't know what this means.
compensate 				= 0;
// hight of the ramps mounts (spacing between the bottom and the board)
ramps_z_spacing 		= 5;
// bridge the front (and back in any) with a Xmm bridge. should match the hight of your lid fan (if selected)
bridgetop				= 20;
// diameter of the self tapping screws to mount the board and the lid
metallscrew_d			= 2.8;
// length of the self tapping screws to mount the lid
metallscrew_l 			= 30;
// diameter of the fan (if any)
fan_d 					= 60;
// diameter the the mounting holes of the fan
fan_screws_d 			= 4.4;
// x/y offset of the screw holes from the center of the fan
fan_offset_screws 		= 25;

/* [Hidden] */

ramps_x = 60.50;
ramps_y = 101.62;
ramps_z = box_hight;

fan_screws_r 			= fan_screws_d/2;
metallscrew_r 			= metallscrew_d/2;
screw_m3_r				= 1.6;
fan_r 					= fan_d/2;
backfan					= backstyle==2?true:false;
backopening				= backstyle==1?true:false;
thickness_lid 			= factor_lid*single_wall;
thickness_bottom 		= factor_bottom*single_wall;
thickness_front 		= factor_front*single_wall;
thickness_back 		    = factor_back*single_wall;
thickness_left 		    = factor_left*single_wall;
thickness_right 		= factor_right*single_wall;
ticknesss_corners 		= factor_corners*single_wall;
ticknesss_boardmounts 	= factor_boardmounts*single_wall;

ramps_calc_y = smartadapter?ramps_y+9:ramps_y;
backopening_bottomwall = smartadapter?27:14;

// legacy
knight_extrusion_width	= 20;		// width of the aluminium extrusions used by MetaStasis.DE jCollasius Knight 3D Printer
knight_extrusion_screw_r	= 2.1;	// radius of the used screws for the aluminium extrusions
knightmount				= false;	// add mounting holes for MetaStasis.DE jCollasius Knight 3D Printer
factor_knightmount 	= 3;
thickness_knightmount 	= factor_knightmount*single_wall;

print_part();

module print_part() {
	if (part == 1) {
		rampsbox();
	} else if (part == 2) {
		rampslid();
	} else if (part == 3) {
		rampsbox();
		translate([-(ramps_xtra_left+ramps_x+single_wall*2+ramps_xtra_right+ticknesss_corners*4+metallscrew_d*2),0,0]) rampslid();
	}
}
// #####################################################################################################################################
module cnccube(x=10, y=10, z=10, r=1.5, w=2) {
	difference() {
		union() {
			for(i1=[[-r,-r,0],[-r,y+r,0],[x+r,-r,0],[x+r,y+r,0]]) translate(i1) fncylinder(r=r, h=z);
			translate([x/2,y/2,0]) {
				centercube([x+r*4,y+r*2,z],x=true,y=true);
				centercube([x+r*2,y+r*4,z],x=true,y=true);
			}
		}
		difference() {
			translate([-r*2+thickness_left,-r*2+thickness_front,w]) cube([x+r*4-thickness_left-thickness_right,y+r*4-thickness_front-thickness_back,z]);
			for(i1=[[-r,-r,0],[-r,y+r,0],[x+r,-r,0],[x+r,y+r,0]]) translate(i1) fncylinder(r=r, h=z,enlarge=1);
		}
		for(i1=[[-r,-r,0],[-r,y+r,0],[x+r,-r,0],[x+r,y+r,0]]) translate([i1[0],i1[1],z]) rotate([180,0,0])
            fncylinder(r=metallscrew_r, h=metallscrew_l-thickness_lid,enlarge=2);
	}
}

// #####################################################################################################################################
module rampsbox() {
	difference() {
		union() {
			cnccube(x=ramps_x+ramps_xtra_left+ramps_xtra_right,
                    y=ramps_calc_y+ramps_xtra_front+ramps_xtra_back,
                    z=ramps_z, r=metallscrew_r+ticknesss_corners, w=thickness_bottom);
            translate([ramps_xtra_left,ramps_xtra_front,0]) rampsmount(r=metallscrew_r+ticknesss_boardmounts, h=ramps_z_spacing+thickness_bottom);
			*if(knightmount) { //thickness_left
				translate([-(metallscrew_r+ticknesss_corners)*2,-ticknesss_corners,ramps_z-knight_extrusion_width]) hull() {
					cube([thickness_knightmount,ramps_calc_y+ramps_xtra_front+ramps_xtra_back+ticknesss_corners*2,knight_extrusion_width]);
					translate([0,0,-thickness_knightmount*1.5]) cube([thickness_left,ramps_calc_y++ramps_xtra_front+ramps_xtra_back+ticknesss_corners*2,knight_extrusion_width]);
				}
				translate([-(metallscrew_r+normal_wall)*2,ramps_xtra+ramps_calc_y/2,0]) for(i1=[-1,1]) for(i2=[-1,1])
					translate([0,i1*(ramps_calc_y/3.5)+i2*(knight_extrusion_width/2),0]) centercube([metallscrew_r*2+normal_wall,stable_wall,ramps_z],y=true);
			}
			if(resetbutton) translate([ramps_xtra_left+ramps_x+ramps_xtra_right+ticknesss_corners*2+metallscrew_d+5-compensate*2+ticknesss_corners+single_wall*2,-metallscrew_d-ticknesss_corners*2+5-compensate*2+ticknesss_corners,0]) rampsbutton();
		}
		*if(knightmount) {
			translate([-(metallscrew_r+normal_wall)*2,ramps_xtra_front+ramps_calc_y/2,0]) for(i1=[-1,1])
				translate([0,i1*(ramps_calc_y/3.5),ramps_z-knight_extrusion_width/2]) rotate([0,90,0])
					fncylinder(r=knight_extrusion_screw_r,h=thickness_knightmount,enlarge=1);
		}
		translate([ramps_xtra_left,ramps_xtra_front,thickness_bottom]) rampsmount(r=metallscrew_r, h=ramps_z_spacing+thickness_bottom);
		if(backfan) {
			translate([ramps_x/2+ramps_xtra_left,ramps_calc_y+ramps_xtra_front+ramps_xtra_back+(metallscrew_r+ticknesss_corners)*2+1,ramps_z/2]) rotate([90,0,0])
				fancuts(r_fan=fan_r, r_screws=fan_screws_r, offset_screws=fan_offset_screws, h=thickness_back+2);
		}
		translate([ramps_xtra_left,ramps_xtra_front,ramps_z_spacing+thickness_bottom]) {
			cube([ramps_x,ramps_calc_y,ramps_z]);
			translate([8.26,-metallscrew_r*2-ticknesss_corners*2-1,0.5])
				cube([14.11,thickness_front+2,ramps_z-ramps_z_spacing-thickness_bottom-bridgetop]);
			translate([1.35,-metallscrew_r*2-ticknesss_corners*2-1,14])
				cube([ramps_x-1.35*2,thickness_front+2,ramps_z-14-ramps_z_spacing-bridgetop]);
			if(resetbutton) {
				translate([ramps_x+ramps_xtra_front+(metallscrew_r+ticknesss_corners)*2,35.44,18.07]) rotate([0,-90,0]) fncylinder(r=5,h=(metallscrew_r+ticknesss_corners)*2,enlarge=1);
			}
			if (backopening) {
				translate([1.35,ramps_xtra_front+ramps_calc_y+ramps_xtra_back,backopening_bottomwall])
					cube([ramps_x-1.35*2,metallscrew_r*2+ticknesss_corners*2+2,ramps_z-backopening_bottomwall-ramps_z_spacing-bridgetop]);
			}
		}
		if(mount_type==1) {
			translate([ramps_xtra_left+ramps_x/2,ramps_xtra_front+ramps_calc_y/2,0]) for(i1=[-1,1]) for(i2=[-1,1])
				translate([i1*15,i2*30,0]) fncylinder(r=screw_m3_r,h=thickness_bottom,enlarge=1);
		}
	}
}

// #####################################################################################################################################
module rampsmount(r=1.6, h=10) {
	for(i1=[[2.64,15.16,0],[50.85,13.92,0],[17.73,65.9,0],[45.64,65.9,0],[2.5,90.07,0],[50.85,96.39,0]])
		translate(i1) fncylinder(r=r, h=h);
}

// #####################################################################################################################################
module rampsbutton() {
	union()  {
		fncylinder(r=5-compensate*2,h=ramps_xtra_right+(metallscrew_r+ticknesss_corners)*2-1);
		fncylinder(r=5-compensate*2+ticknesss_corners,h=ramps_xtra_right+(metallscrew_r+ticknesss_corners)*2-1.5-thickness_right);
		translate([0,0,ramps_xtra_right+(metallscrew_r+ticknesss_corners)*2-1]) resize([(5-compensate*2)*2,(5-compensate*2)*2,(5-compensate*2)]) fnsphere(r=5-compensate*2);
	}
}

// #####################################################################################################################################
module rampslid() {
	difference() {
		union() {
			cnccube(x=ramps_x+ramps_xtra_left+ramps_xtra_right, y=ramps_calc_y+ramps_xtra_front+ramps_xtra_back, z=thickness_lid, r=metallscrew_r+ticknesss_corners, w=thickness_lid);
			lidfixture(x=ramps_x+ramps_xtra_left+ramps_xtra_right, y=ramps_calc_y+ramps_xtra_front+ramps_xtra_back, z=thickness_lid, r=metallscrew_r+ticknesss_corners, w=3);
		}
		if (topfan) {
			translate([ramps_x/2+ramps_xtra_left,ramps_xtra_front+60.45-fan_r/2,-1])
			fancuts(r_fan=fan_r, r_screws=fan_screws_r, offset_screws=fan_offset_screws, h=thickness_lid+2);
		}
	}
}

// #####################################################################################################################################
module lidfixture(x=10, y=10, z=10, r=1.5, w=2) {
	difference() {
		for(i1=[[-r,-r,0],[-r,y+r,0],[x+r,-r,0],[x+r,y+r,0]]) translate(i1) fncylinder(r=r+compensate*2+ticknesss_corners, h=z+w);
		for(i1=[[-r,-r,0],[-r,y+r,0],[x+r,-r,0],[x+r,y+r,0]]) translate(i1) fncylinder(r=r+compensate*2, h=z+w,enlarge=1);
		difference() {
			translate([-r*2-w*2,-r*2-w*2,-1]) cube([x+r*4+w*4,y+r*4+w*4,z+w+2]);
			translate([-r,-r,-2]) cube([x+r*2,y+r*2,z+w+4]);
		}
		for(i1=[[-r,-r,0],[-r,y+r,0],[x+r,-r,0],[x+r,y+r,0]]) translate([i1[0],i1[1],z-30]) fncylinder(r=metallscrew_r, h=31);
	}
}

// #####################################################################################################################################
module fancuts(r_fan=60/2, r_screws=4.3/2, offset_screws=50/2, h=20) {
	translate([0,0,0]) fncylinder(r=r_fan, h=h);
	for(i1=[0:3]) rotate([0,0,90*i1]) translate([offset_screws,offset_screws,0]) fncylinder(r=r_screws, h=h);
}

// #####################################################################################################################################
// a rewritten cylinder, with enlarge and dynamic fn
// 2015 cc by nc sa 4.0, Jons Collasius, Hamburg, Germany
module fncylinder(r,r2,d,d2,h,fn,center=false,enlarge=0,pi=3.1415926536){
	translate(center==false?[0,0,-enlarge]:[0,0,-h/2-enlarge]) {
		if (fn==undef) {
			if (r2==undef && d2==undef) {
				cylinder(r=r?r:d?d/2:1,h=h+enlarge*2,$fn=floor(2*(r?r:d?d/2:1)*pi/resolution));
			} else {
				cylinder(r=r?r:d?d/2:1,r2=r2?r2:d2?d2/2:1,h=h+enlarge*2,$fn=floor(2*(r?r:d?d/2:1)*pi/resolution));
			}
		} else {
			if (r2==undef && d2==undef) {
				cylinder(r=r?r:d?d/2:1,h=h+enlarge*2,$fn=fn);
			} else {
				cylinder(r=r?r:d?d/2:1,r2=r2?r2:d2?d2/2:1,h=h+enlarge*2,$fn=fn);
			}
		}
	}
}

// #####################################################################################################################################
// this cube can be centered on any axis
// 2015 cc by nc sa 4.0, Jons Collasius, Hamburg, Germany
module centercube(xyz=[10,10,10],x=false,y=false,z=false) {
	translate([x==true?-xyz[0]/2:0,y==true?-xyz[1]/2:0,z==true?-xyz[2]/2:0]) cube(xyz);
}

// #####################################################################################################################################
// a rewritten sphere, with dynamic fn
// 2015 cc by nc sa 4.0, Jons Collasius, Hamburg, Germany
module fnsphere(r,d,fn,pi=3.1415926536){
	if (fn==undef) {
		sphere(r=r?r:d?d/2:1,$fn=floor(2*(r?r:d?d/2:1)*pi/resolution));
	} else {
		sphere(r=r?r:d?d/2:1,$fn=fn);
	}
}

```


[User]
Hi! I'm looking to create a customizable wheel for a small robot project, and I want to use OpenSCAD. I've seen a few designs, but I'd like something that I can really tweak. I have some ideas and requirements, and I'm hoping you can help me generate the necessary SCAD code.

Essentially, I need a wheel that has a few different configurations. The core design should include a cylindrical rim and a central hub for mounting onto a motor shaft. The hub needs a specific cutout to fit a motor shaft with a flat side, and a set screw hole for secure attachment. I would also like the option of removing all features other than the hub to generate a test fit piece. I also want to be able to add text to the side of the wheel or add cutout spokes for weight reduction. Finally, I want to be able to adjust the size and tolerances to get a perfect fit.

Here’s a more detailed breakdown of the parameters and features I’m looking for:

**Global Options:**

*   I'd like a variable to select the "features" I want on the wheel, which can be either "spokes," "text," "plain," or "hub-only".

**Wheel Parameters:**

*   `wheel_diameter`: I need to be able to specify the overall diameter of the wheel in millimeters.
*   `fudge_factor`: I want a way to add a small tolerance to the shaft cutout, just in case my printer isn't perfectly calibrated. This should be a variable in millimeters.

**Hub Specifics:**

*   The hub should have a diameter of 12mm and a height of 10mm.
*   The shaft cutout should be a cylindrical hole with a flat side. The base dimensions of the cylindrical portion should be 5.5mm diameter and the width of the flat should be 3mm (but these should both be modifiable with `fudge_factor`). The cutout should be 12 mm deep and start 0.6 mm below the top of the hub. The flat side of the cutout should start 4mm from the top of the hub.
*   The set screw hole should be an M3 size (3mm diameter) and should be centered and drilled through the hub starting at 7mm up from the bottom of the hub.

**Text Feature:**

*   `text`: I'd like to have a text variable to add text to the wheel's surface, like a label or project name.
*   `font`: I need to specify the font, and I'd like a good collection to choose from: "orbitron.dxf", "BlackRose.dxf", "knewave.dxf", "braille.dxf", "Letters.dxf". I expect these fonts to be loaded from some existing library.
*   `letter_depth`: The depth of the engraved/extruded letters. This should be adjustable. A value of 0 should effectively remove the text feature.
*   `letter_spacing`: I need to be able to adjust the spacing between the letters.
*   `letter_height`: Finally, I need a way to adjust the height of the letters.

**Spokes Feature:**

*   If I choose the "spokes" feature, I'd like 6 circular cutouts equally spaced around the wheel.
*   The spoke cutouts should have a radius that is adjustable as a fraction of the wheel radius.
*   The spokes should start a set distance from the center of the wheel and be a little thinner than the rim thickness.

**Rim Details:**

*   The rim should be 4mm thick.
*   I’d also like a small groove on the rim to help with O-ring traction. This should be a small square channel centered on the rim's outer edge.

I think that covers everything! I don't know how to use libraries other than the built-in OpenSCAD modules, but I am aware that there are things called font libraries that can help with using more complicated fonts. Please let me know if you need any more clarification.

[Assistant]
Wheel.scad:
```
// Original script by Mark Benson
// http://www.thingverse.com/thing:122070
// 23/07/2013

// Wheel for maze mouse
// Shaft fitting for 28BYJ-48 geared stepper

// Modified by 648.ken@gmail.com Jun 2015
// Lengthened hub
// increased shaft cutout
// Included M3 set screw hole (might need to be tapped)
// Added parameters for customizer

// Creative commons non commercial

// http://www.thingiverse.com/thing:16193/
use <write/Write.scad>

/* [Global] */
features = "spokes"; // [spokes, text, plain, hub-only]

/* [Wheel] */
// Diameter of wheel in mm.
wheel_diameter = 60;

// Increase shaft cutout size in mm if your printer is not calibrated.
fudge_factor = 0;

/* [Text] */

// You will have to flip it around to see it.
text = "ChickTech  Rules!";

// Font selection
font = "orbitron.dxf"; // [orbitron.dxf, BlackRose.dxf, knewave.dxf, braille.dxf, Letters.dxf]

// 8mm goes all the way through, but may cause trouble with letters like "B".
letter_depth = 1; // [0:8]

// Letter spacing
letter_spacing = 1.2;

// Letter height in mm.
letter_height = 8;

difference(){
	union()	{
		//rim
        if (features != "hub-only"){
            cylinder(r=wheel_diameter / 2, h=4, $fn=100);
        }

		//boss
		cylinder(r=12 / 2, h=10, $fn=100);
	}

	union()	{
		//shaft cutout (shaft with flat)
		translate([0, 0, 0.6])
		intersection(){
			cylinder(r=5.5 / 2 + fudge_factor, h=12, $fn=40); // was 5
			translate([0, 0, 4]) cube([3.0 + fudge_factor, 12, 12],
                                       center=true); // was 2.5
		}

		// set screw for M3
		translate([0, 0, 7])
		rotate([90, 0, 90])
		cylinder(r=1.5, h=60, center=true, $fn=40); // was 1

		//rim groove cutout
		translate([0, 0, 2])
		rotate_extrude(convexity=10, $fn=100)
		translate([wheel_diameter / 2, 0, 10])
		rotate([0,0,45])
		square([2,2],center=true);

        // add text to face
        if (features == "text"){
            if(letter_depth > 0){
                rotate(180, [1, 0, 0]){
                    writecircle(text, [0, 0, 0],
                                wheel_diameter / 2 - letter_height,
                                font=font, space=letter_spacing,
                                t=letter_depth, h=letter_height);
                }
            }
        }
        // add spokes (circular cut-outs)
        if (features == "spokes"){
            for(i = [0:5]){
                rotate(i * 360 / 6, [0, 0, 1])
                translate([wheel_diameter / 3.2, 0, -1])
                cylinder(r=wheel_diameter / 8, h=8, $fn=40);
            }
        }
	}
}

```


[User]
I'm looking to create a parametric model of an E3D-v6 Volcano All Metal HotEnd in OpenSCAD, similar to the design I've seen, but with more flexibility. I want to be able to easily adjust key dimensions and features, so I don't have to tweak the code every single time.

Specifically, I'd like to be able to control the following parameters:

*   **Overall Dimensions:**
    *   The diameter and height of each cylindrical section that makes up the hotend body. There are a few different diameter and height sections.
    *   The overall height of the hotend, which should adjust the various section heights appropriately to maintain overall proportions.
    *   The length of the heat sink fins, the distance between them and how many there are.
*   **Nozzle Area:**
    *   The diameter and height of the lower nozzle section where the filament comes out, as well as the upper thread.
    *   The length of the transition from the main body to the nozzle.
*   **Mounting Features:**
    *   The dimensions of the mounting block (the chamfered cube) and its position relative to the hotend body.
    *   The dimensions of the mounting holes, including their diameter and position.
*   **Internal Features:**
    *   The internal diameter of the hotend and the transition from the main bore to the nozzle.
    *   The depth and position of the internal bore where the bowden tube enters.
*   **Material and tolerances:**
   *   Be able to adjust the tolerances for each fit of all cylinders.
*   **Fin Detail:**
    *   The fin shape, which I would like to be able to choose between a few different shapes.
*   **Resolution:**
    *   A variable to adjust resolution using $fn.

I'd like the OpenSCAD model to be created using modules for each section, so it's well-organized. Also, I'd like to be able to easily hide or show different parts of the design. For instance, I may just want to look at the hotend body without the fins or mounting block to verify the overall dimensions.

I’m not particular about the style of code, but would prefer well-commented code to make it clear what each section does and would like to avoid use of undocumented functions or libraries. I would also prefer to use functions rather than modules when appropriate.

Could you generate the necessary OpenSCAD files for this parametric hotend design? I'd like to avoid any included libraries, too; just raw OpenSCAD code.

[Assistant]
e3d_v6_volcano_all_metall_hotend.scad:
```
/*
Name: E3D-v6 Volcano All Metal HotEnd in OpenSCAD
Author: Jons Collasius from Germany/Hamburg

License: CC BY-NC-SA 4.0
License URL: https://creativecommons.org/licenses/by-nc-sa/4.0/

Creator of "E3D-v6 All Metal HotEnd": E3D Online - JR
URL E3D v6: http://wiki.e3d-online.com/wiki/E3D-v6_Documentation
URL E3D Volcano: http://wiki.e3d-online.com/wiki/E3D-v6_%28Volcano%29_Documentation
*/

/* [Global] */

// resolution of round object. each line segment is fnr mm long. fnr = 1 crude and good for development (its faster), aim for fnr = 0.4 or smaller for a production render. smaller means more details (and a lot more time to render).
fnresolution = 0.4;
// detail level
detaillevel = 1; // [0:coarse render only outlines,1:fine render with all details]

print_part();

module print_part() {
	e3d();
}

module e3d() {
	difference() {
		union() {
			translate([0,0,0]) fncylinder(r=8,h=7);
			translate([0,0,6]) fncylinder(r=6,h=8);
			translate([0,0,13]) fncylinder(r=8,h=8);
			translate([0,0,20]) fncylinder(r=11.15,h=26);
			translate([0,0,0]) fncylinder(r=8,h=7);
			translate([0,0,45]) fncylinder(r=2,h=4.1);
			translate([-4.5,-4.5,49.6]) chamfercube([11.5,20,18.5],side=[0.4,0.4,0.4,0.4],top=[0.4,0.4,0.4,0.4],bottom=[0.4,0.4,0.4,0.4]);
			translate([-4.5,-4.5,48.1]) chamfercube([11.5,12,5],side=[0.4,0.4,0.4,0.4],top=[0.4,0.4,0.4,0.4],bottom=[0.4,0.4,0.4,0.4]);
			translate([0,0,67.1]) fncylinder(r=2.5,h=3);
			translate([0,0,69.1]) fncylinder(r=4.03,h=3,fn=6);
			translate([0,0,71.1]) fncylinder(r=3,r2=0.5,h=3);
		}
		if(detaillevel==1) {
			translate([0,0,-1]) fncylinder(r=1.6,h=64.1);
			translate([0,0,62.1]) fncylinder(r=0.25,h=4,fn=10);
			translate([0,0,16]) fnpipe(r=9,r2=4.475,h=1.5);
			translate([0,0,18.5]) fnpipe(r=9,r2=4.475,h=1.5);
			for ( i = [0 : 9] ) {
				translate([0,0,21+i*2.5]) fnpipe(r=12.15,r2=4.475+i*0.15,h=1.5);
			}
			translate([-0.5,7.5,47.1]) fncylinder(r=3.05, h=22);
			translate([-1.5,7.5,47.1]) cube([2,8.5,22]);
			translate([-5.5,13,52.6]) rotate([0,90,0]) fncylinder(r=1.4, h=13.5);
			translate([-5.5,13,61.6]) rotate([0,90,0]) fncylinder(r=1.4, h=13.5);
			translate([-5.5,13,52.6]) rotate([0,90,0]) fncylinder(r=1.6, h=5.2);
			translate([-5.5,13,61.6]) rotate([0,90,0]) fncylinder(r=1.6, h=5.2);
			translate([8,4,59.1]) rotate([0,-90,0]) fncylinder(r=1.4, h=4.45);
			translate([8,4,62.6]) rotate([0,-90,0]) fncylinder(r=0.9, h=3);
			translate([8,4,62.6]) rotate([0,-90,0]) fncylinder(r=0.75, h=5.45);
		}
	}
}

module chamfercube(xyz=[0,0,0],side=[0,0,0,0],top=[0,0,0,0],bottom=[0,0,0,0],x=false,y=false,z=false) {
	translate([x==true?-xyz[0]/2:0,y==true?-xyz[1]/2:0,z==true?-xyz[2]/2:0]) difference() {
		cube(xyz);
		if(side[0]>=0) translate([0,0,xyz[2]/2]) rotate([0,0,45]) cube([side[0]*2,side[0]*3,xyz[2]+2],center=true);
		if(side[1]>=0) translate([xyz[0],0,xyz[2]/2]) rotate([0,0,-45]) cube([side[1]*2,side[1]*3,xyz[2]+2],center=true);
		if(side[2]>=0) translate([xyz[0],xyz[1],xyz[2]/2]) rotate([0,0,45]) cube([side[2]*2,side[2]*3,xyz[2]+2],center=true);
		if(side[3]>=0) translate([0,xyz[1],xyz[2]/2]) rotate([0,0,-45]) cube([side[3]*2,side[3]*3,xyz[2]+2],center=true);
		if(top[0]>=0) translate([xyz[0]/2,0,xyz[2]]) rotate([-45,0,0]) cube([xyz[0]+2,top[0]*2,top[0]*3,],center=true);
		if(top[2]>=0) translate([xyz[0]/2,xyz[1],xyz[2]]) rotate([45,0,0]) cube([xyz[0]+2,top[2]*2,top[2]*3,],center=true);
		if(top[3]>=0) translate([0,xyz[1]/2,xyz[2]]) rotate([0,45,0]) cube([top[3]*2,xyz[1]+2,top[3]*3,],center=true);
		if(top[1]>=0) translate([xyz[0],xyz[1]/2,xyz[2]]) rotate([0,-45,0]) cube([top[1]*2,xyz[1]+2,top[1]*3,],center=true);
		if(bottom[0]>=0) translate([xyz[0]/2,0,0]) rotate([45,0,0]) cube([xyz[0]+2,bottom[0]*2,bottom[0]*3,],center=true);
		if(bottom[2]>=0) translate([xyz[0]/2,xyz[1],0]) rotate([-45,0,0]) cube([xyz[0]+2,bottom[2]*2,bottom[2]*3,],center=true);
		if(bottom[3]>=0) translate([0,xyz[1]/2,0]) rotate([0,-45,0]) cube([bottom[3]*2,xyz[1]+2,bottom[3]*3,],center=true);
		if(bottom[1]>=0) translate([xyz[0],xyz[1]/2,0]) rotate([0,45,0]) cube([bottom[1]*2,xyz[1]+2,bottom[1]*3,],center=true);
	}
}

// ######################################################################################################################
module fnpipe(r,r2,h,fn){
	if (fn==undef) {
		difference() {
			fncylinder(r=r,h=h,$fn=2*r*3.14/fnresolution);
			translate([0,0,-1]) fncylinder(r=r2,h=h+2,$fn=2*r*3.14/fnresolution);
		}
	} else {
		difference() {
			fncylinder(r=r,h=h,fn=fn);
			translate([0,0,-1]) fncylinder(r=r2,h=h+2,fn=fn);
		}
	}
}

// ######################################################################################################################
module fncylinder(r,r2,h,fn){
	if (fn==undef) {
		if (r2==undef) {
			cylinder(r=r,h=h,$fn=2*r*3.14/fnresolution);
		} else {
			cylinder(r=r,r2=r2,h=h,$fn=2*r*3.14/fnresolution);
		}
	} else {
		if (r2==undef) {
			cylinder(r=r,h=h,$fn=fn);
		} else {
			cylinder(r=r,r2=r2,h=h,$fn=fn);
		}
	}
}
```


[User]
I'd like to design a parametric ethernet cable holder that can be 3D printed. I need it to have a flat base with a number of slots to hold the cables, and it also needs to have some screw holes so it can be mounted to a wall or desk.

Specifically, I want to be able to control the following parameters:

*   **`widthOfBody`:** The width of the main flat base.
*   **`heightOfBody`:** The height/thickness of the main flat base.
*   **`numberOfSlots`:** The number of ethernet cable slots on the holder.
*   **`widthOfSlots`:** The width of each individual cable slot.
*   **`widthOfScrew`:** The diameter of the screw holes.
*    **`widthOfWalls`:** The width of the material separating the slots.

The design should include:

1.  A rectangular base with a configurable width, height, and automatically calculated length based on the number of slots and wall widths.
2.  Two screw holes, one at each end of the base, that go all the way through.
3.  A counterbore at each screw hole.
4.  A series of rounded, rectangular slots to hold the cables. These slots should have an opening facing the top of the design. They should also have a rounded end facing the back of the base.
5.  The slots should be evenly spaced along the length of the base, with the specified `widthOfWalls` separating each.

I'm imagining something that looks a bit like a long, flat box with a bunch of semi-circular cutouts along the top edge, with screw holes on either end. I'd also like the design to be fully parametric using OpenSCAD. I do not need any specific libraries for this.

[Assistant]
Ethernet.scad:
```
//Resolution of the curves.(Higher = more polygons and higher load time)
$fn = 30;
//What would you like the width to be?(mm)
widthOfBody     = 20;
//What would you like the height to be?(mm)
heightOfBody    = 12;
//How many slots do you want?(int)
numberOfSlots   = 5;
//How wide should the slots be?(mm)
widthOfSlots    = 8;
//How wide should the screw hole be?(mm)
widthOfScrew    = 4;
//How wide do you want the seperating walls?(mm)
widthOfWalls    = 5;

lengthOfBody    = (widthOfBody) + ( widthOfSlots * numberOfSlots ) + ( widthOfWalls * ( numberOfSlots - 1 ) );
difference(){
    union(){
        cube([widthOfBody, lengthOfBody, heightOfBody]);
        translate([ widthOfBody / 2, 0, 0]){
            cylinder( d = widthOfBody, h = heightOfBody );
            translate([ 0, lengthOfBody, 0]){
                cylinder( d = widthOfBody, h = heightOfBody );
            }
        }
    }
    union(){
        translate([ widthOfBody / 2, 0, -1 ]){
            cylinder( d = widthOfScrew, h = heightOfBody + 2 );
            translate([ 0, lengthOfBody, 0]){
                cylinder( d = widthOfScrew, h = heightOfBody + 2 );
            }
        }
        translate([ widthOfBody / 2, 0, heightOfBody - ( heightOfBody / 6 ) + 0.01]){
            cylinder( d1 = widthOfScrew, d2 = widthOfScrew * 2, h = ( heightOfBody / 6 ) );
            translate([ 0, lengthOfBody, 0]){
                cylinder( d1 = widthOfScrew, d2 = widthOfScrew * 2, h = 2 );
            }
        }
        for( i = [ 1 : numberOfSlots ] ){
            translate([-1, ( ( widthOfBody / 2 ) ) + ( ( i - 1 ) * widthOfWalls ) + ( ( i - 1) * widthOfSlots ),-1]){
                cube( [ 2 + widthOfBody, widthOfSlots, 1 + ( widthOfSlots / 2 ) ] );

                translate([0, widthOfSlots / 2, widthOfSlots / 2 ]){
                    rotate( a = [ 0, 90, 0 ] ){
                        cylinder( d = widthOfSlots, h = 2 + widthOfBody );
                    }
                }
            }
        }
    }
}

```


[User]
Hey there! I'm looking to create a parametric cable cover for some Molex connectors I have on my CNC mill. I want to be able to adjust the dimensions to fit different connectors in the future, and I've got some specific ideas on how it should work.

Essentially, I need a two-part cover that snaps together. Think of a rectangular box, but instead of a solid bottom, one of the parts will have a lip that fits into the other, making it a snap fit.

Here are the parameters I need to control:

*   `cavity_length`: The length of the cavity that holds the connectors.
*   `cavity_width`: The width of the cavity.
*   `cavity_depth`: The depth of the cavity.
*   `wall_thickness`: The thickness of the cover's walls.
*   `cable_diam`: The diameter of the cable that will pass through the cover.

The cover should have a rounded rectangle shape. I want to use a `rrect()` type function for the overall shape with a radius of maybe 5.

The top part of the cover will have a cavity that fits around the connectors. This cavity should have rounded corners on the inside, with a smaller radius like 3. It should also have an extrusion with a small lip to create the snap fit with the bottom piece. The snap fit needs a rounded rectangular lip that is on the outside of the bottom piece and on the inside of the top piece.

The bottom part of the cover should be mostly flat with just a lip for the snap fit to hold onto. And there should be a mating inner space, just like on the top part.

Both parts should have a cutout for the cable to pass through. This cutout should be a rounded cut, wide enough for the cable diameter. I'd like to use a cylinder to create this. It would be best to create the cable cutouts using `hull` in order to guarantee that the cut goes all the way through.

I think I'll also need some small, rounded pegs that will snap into matching holes to help with alignment on the mating surfaces of the top and bottom cover halves. I think using a slightly smaller diameter for the peg than the hole would be good for ensuring the parts snap together, maybe 3 and 4 mm?

Could you generate the necessary OpenSCAD files to accomplish this? I'm already using the Belfry OpenSCAD Library so you don't need to include that, but please use the functions as shown in my example code.

[Assistant]
CableCover.scad:
```

// Length of cavity to hold connectors.
cavity_length = 50; // [5:100]

// Width of cavity to hold connectors.
cavity_width  = 25; // [5:100]

// Depth of cavity to hold connectors.
cavity_depth  = 10; // [5:100]

// Thickness of the cover's wall.
wall_thickness = 3; // [2:10]

// Diameter of the cable to cover.
cable_diam = 5; // [1:10]

///////////////////////////////////////////////////////////////
// From Belfry OpenSCAD Library: Placement and Duplication

module right(x) translate([+x,0,0]) children();
module left(x)  translate([-x,0,0]) children();
module back(y)  translate([0,+y,0]) children();
module fwd(y)   translate([0,-y,0]) children();
module up(z)    translate([0,0,+z]) children();
module down(z)  translate([0,0,-z]) children();

module xrot(x) rotate([x,0,0]) children();
module yrot(y) rotate([0,y,0]) children();
module zrot(z) rotate([0,0,z]) children();

module xscale(x) scale([x,1,1]) children();
module yscale(y) scale([1,y,1]) children();
module zscale(z) scale([1,1,z]) children();

module xflip() mirror([1,0,0]) children();
module yflip() mirror([0,1,0]) children();
module zflip() mirror([0,0,1]) children();

module xskew(ya=0,za=0) multmatrix([[1,0,0,0], [tan(ya),1,0,0], [tan(za),0,1,0], [0,0,0,1]]) children();
module yskew(xa=0,za=0) multmatrix([[1,tan(xa),0,0], [0,1,0,0], [0,tan(za),1,0], [0,0,0,1]]) children();
module zskew(xa=0,ya=0) multmatrix([[1,0,tan(xa),0], [0,1,tan(ya),0], [0,0,1,0], [0,0,0,1]]) children();

module mirror_copy(v) {children(); mirror(v) children();}
module xflip_copy() {children(); mirror([1,0,0]) children();}
module yflip_copy() {children(); mirror([0,1,0]) children();}
module zflip_copy() {children(); mirror([0,0,1]) children();}

module move_copies(a=[[0,0,0]]) {for (p = a) translate(p) children();}
module xrot_copies(rots=[0]) {for (r = rots) rotate([r, 0, 0]) children();}
module yrot_copies(rots=[0]) {for (r = rots) rotate([0, r, 0]) children();}
module zrot_copies(rots=[0]) {for (r = rots) rotate([0, 0, r]) children();}

module xspread(spacing=1,n=2) {off=spacing*(n-1)/2.0; for (x =[-off:spacing:off]) translate([x, 0, 0]) children();}
module yspread(spacing=1,n=2) {off=spacing*(n-1)/2.0; for (y =[-off:spacing:off]) translate([0, y, 0]) children();}
module zspread(spacing=1,n=2) {off=spacing*(n-1)/2.0; for (z =[-off:spacing:off]) translate([0, 0, z]) children();}
module spread(p1,p2,n=3) {d=(p2-p1)/(n-1); for (i=[0:n-1]) translate(p1+d*i) children();}

module xring(n=2,r=0,rot=true) {d=360.0/n; for (a=[d:d:360]) xrot(a%360) back(r) xrot(rot?0:-a%360) children();}
module yring(n=2,r=0,rot=true) {d=360.0/n; for (a=[d:d:360]) yrot(a%360) right(r) yrot(rot?0:-a%360) children();}
module zring(n=2,r=0,rot=true) {d=360.0/n; for (a=[d:d:360]) zrot(a%360) right(r) zrot(rot?0:-a%360) children();}

module grid_of(xa=[0],ya=[0],za=[0]) {for (x=xa,y=ya,z=za) translate([x,y,z]) children();}

///////////////////////////////////////////////////////////////
// From Belfry OpenSCAD Library: Shapes

module rrect(size=[1,1,1], r=1, center=false)
{
	translate(center?[0,0,0]:size/2) {
		hull() xspread(size[0]-2*r) {
			hull() yspread(size[1]-2*r) {
				cylinder(r=r, h=size[2], center=true);
			}
		}
	}
}

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

$fa = 1*1;
$fs = 1*1;

module cover_top() {
	up((cavity_depth+wall_thickness)/2) {
		difference() {
			rrect(r=5, size=[cavity_length+2*wall_thickness, cavity_width+2*wall_thickness, cavity_depth+wall_thickness], center=true);
			up(wall_thickness/2+0.05) {
				rrect(r=3, size=[cavity_length+wall_thickness, cavity_width+wall_thickness, cavity_depth], center=true);
			}
			hull() {
				up(wall_thickness/2) {
					grid_of(za=[0, cavity_depth]) {
						yrot(90) cylinder(d=cable_diam, h=cavity_length*2, center=true);
					}
				}
			}
			hull() {
				up(cavity_depth/2+wall_thickness/2-0.99) {
					xspread(cavity_length+wall_thickness-6) {
						yspread(cavity_width+wall_thickness-6) {
							cylinder(r1=3, r2=4, h=2, center=true);
						}
					}
				}
			}
		}
	}
}

module cover_bottom() {
	up((cavity_depth+wall_thickness)/2) {
		down(cavity_depth/2) {
			rrect(r=5, size=[cavity_length+2*wall_thickness, cavity_width+2*wall_thickness, wall_thickness], center=true);
		}
		difference() {
			rrect(r=3, size=[cavity_length+wall_thickness, cavity_width+wall_thickness, cavity_depth], center=true);
			rrect(r=2, size=[cavity_length, cavity_width, cavity_depth+0.05], center=true);
			hull() {
				up(wall_thickness/2) {
					grid_of(za=[0, cavity_depth]) {
						yrot(90) cylinder(d=cable_diam, h=cavity_length*2, center=true);
					}
				}
			}
			up(cavity_depth/2+wall_thickness/2-wall_thickness) {
				difference() {
					up(wall_thickness/2)
						rrect(r=5, size=[cavity_length+2*wall_thickness, cavity_width+2*wall_thickness, wall_thickness], center=true);
					hull() {
						xspread(cavity_length+wall_thickness-6) {
							yspread(cavity_width+wall_thickness-6) {
								up(0.99) cylinder(r1=3, r2=2, h=2, center=true);
							}
						}
					}
				}
			}
		}
	}
}

back((cavity_width+2*wall_thickness)/2+2) cover_top();
fwd((cavity_width+2*wall_thickness)/2+2) cover_bottom();

// vim: noexpandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap

```


[User] I need a customizable tube generator. I want to be able to specify the inner and outer radius of the tube, as well as its length. Also, I want the option to cap one end of the tube, specifying the length of the cap. The units should all be in millimeters. The generated tube should be a cylinder with a hole through it, and if a cap is specified, it should fill the cylinder on one end. I'm not looking for any fancy features, just the basic tube with these options. I don't need any specific libraries.

[Assistant]
tube.scad:
```
//*RADIUS* (not diameter!) in mm of the hollow part
inner_radius=16;

//*RADIUS* (not diameter!) in mm of the tube
outter_radius=19;

//tube length in mm
length=35;

//cap the tube on one side and fill it with this amount in mm
cap_length=0;

/* [Hidden] */
circle=500;

difference(){
    cylinder(r=outter_radius,h=length,$fn=circle);
    translate([0,0,-1])cylinder(r=inner_radius,h=length+2,$fn=circle);
}

if (cap_length>0){
    cylinder(r=outter_radius,h=cap_length,$fn=circle);
}
```


[User]
I'm looking to create a parametric badge holder, something that can hold a standard credit card or ID badge securely. I want to be able to adjust the thickness to accommodate multiple cards or a thicker single card. The current badge holders are so flimsy, and I'm hoping a 3D printed version will be much more robust.

Specifically, the holder should have the following features:

1.  **Basic Dimensions:** It should fit a standard credit card-sized card, which is roughly 56mm wide by 87mm high.  I want the design to be flexible so I can adjust it for cards that are a bit thicker than the standard 1mm.
2.  **Wall Thickness:** I’d like a wall thickness for the holder itself to be configurable. Let's start at 2mm.
3.  **Bezel:** The holder should have a small bezel around the card, but I want to control that too.  Let’s make the bezel 3mm bigger than the wall, so the bezel will be 5mm in total.
4.  **Rounded Corners:** It would be nice to have rounded corners on the outer edges of the holder, with a configurable radius; I'm thinking about 4mm to start.
5.  **Card Cutout:** There should be a cutout in the back of the holder that matches the shape of the card to reduce material usage. I'd like to keep the card fairly snug.
6.  **Clip Hole:** I want an oblong hole for attaching a lanyard clip. This needs to be configurable by width, height and location, but it should be towards the top and centered on the width. Let's start with 15mm wide and 4mm tall.
7.  **Parametric Adjustments:** I'd need to be able to adjust the card thickness, card width and card height, holder wall thickness, bezel size, and the radius of the corners of the outer edges. I'd also like to control the clip hole dimensions and location as mentioned above.
8.  **Libraries:** I'd like to use BOSL2 if possible for its features and readability.

Could you generate the necessary OpenSCAD files to create this parametric badge holder for me? I think I only need one file to make this, but if you want to break it out into multiple files, that's fine as long as everything is easy to use.

[Assistant]
hid_badge_holder.scad:
```
badge_thickness = 1;

/* [Hidden] */
badge_width = 56;
badge_height = 87;

holder_wall_size = 2;
holder_bezel_size = holder_wall_size + 3;

holder_height = badge_height + (holder_wall_size * 2);
holder_width = badge_width + (holder_wall_size * 2);
holder_thickness = badge_thickness  + (holder_wall_size * 2);
holder_radius = 4;

clip_hole_width = 15;
clip_hole_height = 4;

difference() {
  hull() {
    cube(size=[holder_height - holder_radius, holder_width, holder_thickness]);

    translate([holder_height - holder_radius, holder_radius, 0])
      cylinder(h=holder_thickness, r=holder_radius, $fn=200);
    translate([holder_height - holder_radius, holder_width - holder_radius, 0])
      cylinder(h=holder_thickness, r=holder_radius, $fn=200);
  }

  translate([holder_wall_size,holder_wall_size, holder_wall_size])
    cube(size=[badge_height, badge_width, badge_thickness]);

  translate([holder_wall_size,holder_wall_size, holder_wall_size])
    cube(size=[badge_height / 2.25, badge_width, holder_thickness * 2]);

  hull() {
    translate([holder_bezel_size + holder_radius, holder_bezel_size + holder_radius, 0])
      cylinder(h=holder_thickness, r=holder_radius, $fn=200);
    translate([holder_bezel_size + holder_radius, holder_width - holder_bezel_size - holder_radius, 0])
      cylinder(h=holder_thickness, r=holder_radius, $fn=200);
    translate([holder_height - holder_bezel_size - holder_radius, holder_bezel_size + holder_radius, 0])
      cylinder(h=holder_thickness, r=holder_radius, $fn=200);
    translate([holder_height - holder_bezel_size - holder_radius, holder_width - holder_bezel_size - holder_radius, 0])
      cylinder(h=holder_thickness, r=holder_radius, $fn=200);
  }
}

difference() {
  translate([holder_width - 8.05, holder_width / 2, 0])
    cylinder(h=holder_thickness, d=holder_width * 2, $fn=200);

  translate([0, holder_width * -1.5, -1])
    cube(holder_width * 3, holder_width * 3, 100);

  translate([(clip_hole_height / -2) - 1, (holder_width - (clip_hole_width + (clip_hole_height / 2))) / 2, -.5])
  hull() {
    translate([0,clip_hole_width,0])
      cylinder(h=holder_thickness + 1, d=clip_hole_height, $fn=100);
    cylinder(h=holder_thickness + 1, d=clip_hole_height, $fn=100);
  }
}
```


[User]
I'd like to create a customizable six-sided die (D6) with unique symbols on each face, using OpenSCAD. I need it to be parametric so I can easily change the size, depth of the engravings, corner roundness, and even the characters used on each face. I'm also hoping to be able to use any font available in OpenSCAD and to control the scaling of each character.

Specifically, I envision the design working like this:

*   **Shape:** A cube with rounded corners. The amount of rounding should be adjustable (think a slider from a sharp cube to a very round almost-sphere).
*   **Faces:** Each face should have an engraved character, like you'd see on a normal die. The characters should be customizable, allowing for Unicode symbols, as well as regular text. I want to be able to scale each character independently.
*   **Engraving:** The engravings should be recessed into the surface of the die. The depth of the engravings should also be parametric.
*   **Font:** I need to be able to specify the font used for the symbols on each face. It would be ideal if it used all fonts available within OpenSCAD.
*   **Parameters:** I'd expect the following parameters to be configurable:
    *   `cube_size`: The length of a side of the cube in mm.
    *   `depth`: The depth of the engravings in mm.
    *   `curvature`: A value controlling the corner roundness (1 being a cube, higher values making it more spherical).
    *   `text_1` through `text_6`: The characters/symbols for each face of the die.
    *   `scale_1` through `scale_6`: Scaling factors for each character/symbol.
    *   `font`: The name of the font to be used for all symbols.

Essentially, I need a D6 generator that is highly customizable. I'm not using any external libraries, but if there's a good reason to use one, please let me know.

[Assistant]
Unicode_D6.scad:
```
//Created by Ari M. Diacou, June 2015
//Shared under Creative Commons License: Attribution-ShareAlike 3.0 Unported (CC BY-SA 3.0)
//see http://creativecommons.org/licenses/by-sa/3.0/

/* [Characters] */
// use any letters, numbers or unicodes, see http://en.wikipedia.org/wiki/List_of_Unicode_characters or my favorite http://www.decodeunicode.org/
text_1= "\u262b";
scale_1=1;
text_2= "\u2616";
scale_2=.8;
text_3= "\u2616";
scale_3=.8;
text_4= "\u2620";
scale_4=.85;
text_5= "\u2620";
scale_5=.85;
text_6= "\u2620";
scale_6=.85;
/* [Dimensions] */
//Depth of indendations in mm
depth=2;
//One side of the cube in mm
cube_size=25;
//How much of the corners should be cut off? Higher is more spherical, 1 is a cube. Recommend 1.0-2.0.
curvature=1.42;
//DejaVu Sans was the font I found on this list with the most Unicode 7 implementations
font = "DejaVu Sans"; //[ABeeZee,Abel,Abril Fatface,Aclonica,Acme,Actor,Adamina,Advent Pro,Aguafina Script,Akronim,Aladin,Aldrich,Alef,Alegreya,Alegreya Sans,Alegreya Sans SC,Alegreya SC,Alex Brush,Alfa Slab One,Alice,Alike,Alike Angular,Allan,Allerta,Allerta Stencil,Allura,Almendra,Almendra Display,Almendra SC,Amarante,Amaranth,Amatic SC,Amethysta,Amiri,Anaheim,Andada,Andada SC,Andika,Angkor,Annie Use Your Telescope,Anonymous Pro,Antic,Antic Didone,Antic Slab,Anton,Antonio,Arapey,Arbutus,Arbutus Slab,Architects Daughter,Archivo Black,Archivo Narrow,Arial,Arial Black,Arimo,Arizonia,Armata,Artifika,Arvo,Asap,Asset,Astloch,Asul,Atomic Age,Aubrey,Audiowide,Autour One,Average,Average Sans,Averia Gruesa Libre,Averia Libre,Averia Sans Libre,Averia Serif Libre,Bad Script,Balthazar,Bangers,Basic,Battambang,Baumans,Bayon,Belgrano,Belleza,BenchNine,Bentham,Berkshire Swash,Bevan,Bhavuka,Bigelow Rules,Bigshot One,Bilbo,Bilbo Swash Caps,Bitter,Black Ops One,Bokor,Bonbon,Boogaloo,Bowlby One,Bowlby One SC,Brawler,Bree Serif,Bruno Ace,Bruno Ace SC,Bubblegum Sans,Bubbler One,Buda,Buenard,Butcherman,Butcherman Caps,Butterfly Kids,Cabin,Cabin Condensed,Cabin Sketch,Caesar Dressing,Cagliostro,Calligraffitti,Cambay,Cambo,Candal,Cantarell,Cantata One,Cantora One,Capriola,Cardo,Carme,Carrois Gothic,Carrois Gothic SC,Carter One,Caudex,Cedarville Cursive,Ceviche One,Changa,Changa One,Chango,Chau Philomene One,Chela One,Chelsea Market,Chenla,Cherry Cream Soda,Cherry Swash,Chewy,Chicle,Chivo,Cinzel,Cinzel Decorative,Clara,Clicker Script,Coda,Coda Caption,Codystar,Combo,Comfortaa,Comic Sans MS,Coming Soon,Concert One,Condiment,Content,Contrail One,Convergence,Cookie,Copse,Corben,Courgette,Cousine,Coustard,Covered By Your Grace,Crafty Girls,Creepster,Creepster Caps,Crete Round,Crimson Text,Croissant One,Crushed,Cuprum,Cutive,Cutive Mono,Damion,Dancing Script,Dangrek,Dawning of a New Day,Days One,DejaVu Sans,Dekko,Delius,Delius Swash Caps,Delius Unicase,Della Respira,Denk One,Devonshire,Dhurjati,Dhyana,Didact Gothic,Dinah,Diplomata,Diplomata SC,Domine,Donegal One,Doppio One,Dorsa,Dosis,Droid Arabic Kufi,Droid Arabic Naskh,Droid Sans,Droid Sans Ethiopic,Droid Sans Mono,Droid Sans Thai,Droid Serif,Droid Serif Thai,Dr Sugiyama,Duru Sans,Dynalight,Eagle Lake,Eater,Eater Caps,EB Garamond,Economica,Eczar,Ek Mukta,Electrolize,Elsie,Elsie Swash Caps,Emblema One,Emilys Candy,Encode Sans,Encode Sans Compressed,Encode Sans Condensed,Encode Sans Narrow,Encode Sans Wide,Engagement,Englebert,Enriqueta,Erica One,Esteban,Euphoria Script,Ewert,Exo,Exo 2,Expletus Sans,Fanwood Text,Fascinate,Fascinate Inline,Faster One,Fasthand,Fauna One,Federant,Federo,Felipa,Fenix,Finger Paint,Fira Mono,Fira Sans,Fjalla One,Fjord One,Flamenco,Flavors,Fondamento,Fontdiner Swanky,Forum,Francois One,Freckle Face,Fredericka the Great,Fredoka One,Freehand,Fresca,Frijole,Fruktur,Fugaz One,Gabriela,Gafata,Galdeano,Galindo,Geneva,Gentium Basic,Gentium Book Basic,Geo,Geostar,Geostar Fill,Germania One,GFS Didot,GFS Neohellenic,Gidugu,Gilda Display,Give You Glory,Glass Antiqua,Glegoo,Gloria Hallelujah,Goblin One,Gochi Hand,Gorditas,Goudy Bookletter 1911,Graduate,Grand Hotel,Gravitas One,Great Vibes,Griffy,Gruppo,Gudea,Gurajada,Habibi,Halant,Hammersmith One,Hanalei,Hanalei Fill,Handlee,Hanuman,Happy Monkey,Headland One,Helvetica,Henny Penny,Hermeneus One,Herr Von Muellerhoff,Hind,Holtwood One SC,Homemade Apple,Homenaje,Iceberg,Iceland,IM Fell Double Pica,IM Fell Double Pica SC,IM Fell DW Pica,IM Fell DW Pica SC,IM Fell English,IM Fell English SC,IM Fell French Canon,IM Fell French Canon SC,IM Fell Great Primer,IM Fell Great Primer SC,Imprima,Inconsolata,Inder,Indie Flower,Inika,Inknut Antiqua,Irish Grover,Irish Growler,Istok Web,Italiana,Italianno,Jacques Francois,Jacques Francois Shadow,Jaldi,Jim Nightshade,Jockey One,Jolly Lodger,Josefin Sans,Josefin Sans Std Light,Josefin Slab,Joti One,Judson,Julee,Julius Sans One,Junge,Jura,Just Another Hand,Just Me Again Down Here,Kadwa,Kalam,Kameron,Kantumruy,Karla,Karla Tamil Inclined,Karla Tamil Upright,Karma,Kaushan Script,Kavoon,Kdam Thmor,Keania One,Kelly Slab,Kenia,Khand,Khmer,Khula,Kite One,Knewave,Kotta One,Koulen,Kranky,Kreon,Kristi,Krona One,La Belle Aurore,Laila,Lakki Reddy,Lancelot,Lateef,Lato,League Script,Leckerli One,Ledger,Lekton,Lemon,Lemon One,Liberation Sans ,Libre Baskerville,Libre Caslon Text,Life Savers,Lilita One,Lily Script One,Limelight,Linden Hill,Lobster,Lobster Two,Lohit Bengali,Lohit Tamil,Londrina Outline,Londrina Shadow,Londrina Sketch,Londrina Solid,Lora,Loved by the King,Lovers Quarrel,Love Ya Like A Sister,Luckiest Guy,Lusitana,Lustria,Macondo,Macondo Swash Caps,Magra,Maiden Orange,Mako,Mallanna,Mandali,Marcellus,Marcellus SC,Marck Script,Margarine,Marko One,Marmelad,Martel Sans,Marvel,Mate,Mate SC,Maven Pro,McLaren,Meddon,MedievalSharp,Medula One,Megrim,Meie Script,Merge One,Merienda,Merienda One,Merriweather,Merriweather Sans,Mervale Script,Metal,Metal Mania,Metamorphous,Metrophobic,Miama,Michroma,Milonga,Miltonian,Miltonian Tattoo,Miniver,Miss Fajardose,Miss Saint Delafield,Modak,Modern Antiqua,Molengo,Molle,Monda,Monofett,Monoton,Monsieur La Doulaise,Montaga,Montez,Montserrat,Montserrat Alternates,Montserrat Subrayada,Moul,Moulpali,Mountains of Christmas,Mouse Memoirs,Mr Bedford,Mr Bedfort,Mr Dafoe,Mr De Haviland,Mrs Sheppards,Mrs Saint Delafield,Muli,Mystery Quest,Nanum Brush Script,Nanum Gothic,Nanum Gothic Coding,Nanum Myeongjo,Nanum Pen Script,NATS,Neucha,Neuton,New Rocker,News Cycle,Niconne,Nixie One,Nobile,Nokora,Norican,Nosifer,Nosifer Caps,Nothing You Could Do,Noticia Text,Noto Sans,Noto Sans Hebrew,Noto Sans Symbols,Noto Sans UI,Noto Serif,Nova Cut,Nova Flat,Nova Mono,Nova Oval,Nova Round,Nova Script,Nova Slim,Nova Square,NTR,Numans,Nunito,Odor Mean Chey,Offside,OFL Sorts Mill Goudy TT,Oldenburg,Old Standard TT,Oleo Script,Oleo Script Swash Caps,Open Sans,Open Sans Condensed,Oranienbaum,Orbitron,Oregano,Orienta,Original Surfer,Oswald,Overlock,Overlock SC,Over the Rainbow,Ovo,Oxygen,Oxygen Mono,Pacifico,Palanquin,Palanquin Dark,Paprika,Parisienne,Passero One,Passion One,Pathway Gothic One,Patrick Hand,Patrick Hand SC,Patua One,Paytone One,Pecita,Peddana,Peralta,Permanent Marker,Petit Formal Script,Petrona,Phetsarath,Philosopher,Piedra,Pinyon Script,Pirata One,Plaster,Play,Playball,Playfair Display,Playfair Display SC,Podkova,Poetsen One,Poiret One,Poller One,Poly,Pompiere,Ponnala,Pontano Sans,Poppins,Porter Sans Block,Port Lligat Sans,Port Lligat Slab,Prata,Preahvihear,Press Start 2P,Princess Sofia,Prociono,Prosto One,PT Mono,PT Sans,PT Sans Caption,PT Sans Narrow,PT Serif,PT Serif Caption,Puralecka Narrow,Puritan,Purple Purse,Quando,Quantico,Quattrocento,Quattrocento Sans,Questrial,Quicksand,Quintessential,Qwigley,Racing Sans One,Radley,Rajdhani,Raleway,Raleway Dots,Ramabhadra,Ramaraja,Rambla,Rammetto One,Ranchers,Rancho,Ranga,Rationale,Ravi Prakash,Redacted,Redacted Script,Redressed,Reenie Beanie,Revalia,Ribeye,Ribeye Marrow,Righteous,Risque,Roboto,Roboto Condensed,Roboto Slab,Rochester,Rock Salt,Rokkitt,Romanesco,Ropa Sans,Rosario,Rosarivo,Rouge Script,Rozha One,Rubik Mono One,Rubik One,Ruda,Rufina,Ruge Boogie,Ruluko,Rum Raisin,Ruslan Display,Russo One,Ruthie,Rye,Sacramento,Sail,Salsa,Sanchez,Sancreek,Sansation,Sansita One,Sarabun,Sarala,Sarina,Sarpanch,Satisfy,Scada,Scheherazade,Schoolbell,Seaweed Script,Sedan,Sedan SC,Sevillana,Seymour One,Shadows Into Light,Shadows Into Light Two,Shanti,Share,Share Tech,Share Tech Mono,Shojumaru,Short Stack,Siamreap,Siemreap,Sigmar One,Signika,Signika Negative,Simonetta,Sintony,Sirin Stencil,Six Caps,Skranji,Slabo 13px,Slabo 27px,Slackey,Smokum,Smythe,Sniglet,Snippet,Snowburst One,Sofadi One,Sofia,Sonsie One,Sorts Mill Goudy,Source Code Pro,Source Sans Pro,Source Serif Pro,Special Elite,Spicy Rice,Spinnaker,Spirax,Squada One,Sree Krushnadevaraya,Stalemate,Stalinist One,Stalin One,Stardos Stencil,Stint Ultra Condensed,Stint Ultra Expanded,Stoke,Strait,Strong,Sue Ellen Francisco,Sunshiney,Supermercado One,Suranna,Suravaram,Suwannaphum,Swanky and Moo Moo,Syncopate,Tahoma,Tangerine,Taprom,Tauri,Teko,Telex,Tenali Ramakrishna,Tenor Sans,Terminal Dosis,Terminal Dosis Light,Text Me One,Thabit,The Girl Next Door,Tienne,Tillana,Timmana,Tinos,Titan One,Titillium Web,Trade Winds,Trocchi,Trochut,Trykker,Tuffy,Tulpen One,Ubuntu,Ubuntu Condensed,Ubuntu Mono,Ultra,Uncial Antiqua,Underdog,Unica One,UnifrakturCook,UnifrakturMaguntia,Unkempt,Unlock,Unna,Vampiro One,Varela,Varela Round,Vast Shadow,Verdana,Vesper Libre,Vibur,Vidaloka,Viga,Voces,Volkhov,Vollkorn,Voltaire,VT323,Waiting for the Sunrise,Wallpoet,Walter Turncoat,Warnes,Wellfleet,Wendy One,Wire One,Yanone Kaffeesatz,Yellowtail,Yeseva One,Yesteryear,Zeyada]

/* [Hidden] */
text=[text_1,text_2,text_3,text_4,text_5,text_6];
text_scaling=[scale_1,scale_2,scale_3,scale_4,scale_5,scale_6];
//How each die surface is rotated
rot=[[0,0,0],[90,0,0],[180,0,0],[270,0,0],[0,90,0],[0,-90,0]];
ep=0+0.05; //epsilon, a small number used for alignment and overlap
image_size=cube_size-2*depth-ep; //The size of the images is based on the depth of the cuts so that they wont intersect
///////////////////////// Main() /////////////////////////////////
intersection_for(i=[1:6]){ //Each side is a cube minus the image, the die is the intersection of all the cubes
	sphere(cube_size/curvature);
	side(i);
	}
////////////////////////// Functions //////////////////////////////
module letter(l){
    // Use linear_extrude() to make the letters 3D objects
    linear_extrude(height = depth, convexity=20)
        text(str(l), size = image_size, font = font, halign = "center", valign = "center", $fn = 40);
    }
module side(side_num){
//this function takes the surface, scales it to the right size then subtracts the surface from the cube. The resulting cube is then rotated into the correct position.
	rotate(rot[side_num-1])
		difference(){
			cube(cube_size,true);
			translate([0,0,+cube_size/2-depth+ep])
				scale([text_scaling[side_num-1],text_scaling[side_num-1],1])
                    letter(text[side_num-1]);
			}
	}
```