[User]
I'm looking to get a customisable tripod strap clamp designed in OpenSCAD. I have a basic idea from a previous design, which I can give you, but I'd like a totally new version based on it.

The clamp should consist of two main parts: a "tube" section that wraps around the tripod leg and a flat base with a slot for a strap. The tube part doesn’t necessarily have to be a full cylinder; I’d like it to be parametric so I could choose between a circular, square, or elliptical shape.

Here are the key parameters I need to be able to adjust:

*   **Tube Shape:** (circlular, square, or eliptical)
*   **Tube Width:** This should control the width of the tube section, regardless of shape.
*   **Tube Depth:** This will control the depth of the tube section for the circular/elliptical options, and the depth of the whole tube section for the square tube.
*   **Slot Depth:** The depth of the strap slot base.
*   **Slot Width:** The width of the strap slot.
*   **Overall Height:** The total height of the clamp.
*   **Wall Thickness:** The thickness of the material making up the structure.
*   **Slot Gap:**  The width of the gap at the back of the strap slot.
*   **Tube Gap:** The width of the gap at the front of the tube section.
*   **Mounting Hole Count:** The number of mounting holes (optional).
*   **Mounting Hole Diameter:** The diameter of the mounting holes (if any).

I'd also like a "security strap slot" to run horizontally between the tube and strap slot - I think I had that already, but I want to make sure its included.

I am using metric measurements only (millimeters).

Finally, I'd really like to avoid the issues I had in the previous version with inconsistent use of `center=true/false`, and ensure that everything is properly aligned and centred by default.

Could you generate the OpenSCAD file(s) for me based on these requirements? I don’t need anything special in terms of libraries; just the standard OpenSCAD primitives should be fine.

[Assistant]
Tripod_strap_clamp_1-1.scad:
```
// What shape for the tube?
tube_type = "circlular"; //[circlular,square,elipticle]

// Tube Width (mm)
tubeWidth = 29.5;

// Tube Depth (mm)
tubeDepth = 28;

// Rectangular slot depth (mm)
slotDepth = 5;

// Rectangular slot width (mm)
slotWidth = 50;

// Total height (mm)
height = 29;

// Wall thickness (mm)
wallThickness = 2;

// Width of gap at the back of the rectangular slot (mm)
slotGap = 10;

// Width of gap at the front of the tube (mm)
tubeGap = 18;

// Mounting hole count
numHoles = 0;

// Mounting hole diemeters (mm)
holeDiameter = 4;

module tripodclamp()
{
    tubeRadius = tubeWidth/2;
	difference() {
		// Main body
			union(){
			cube([slotDepth + (2*wallThickness) + 5
					, slotWidth + (2*wallThickness)
					, height], center = false);
			translate([tubeRadius + slotDepth + (wallThickness*2) +4
							,((slotWidth + (wallThickness*2))/2)
							,0])
				cylinder(h=height
							,r=tubeRadius + wallThickness
							,$fn=200);
			}

		// Subractions
			// Belt slot
		translate([slotDepth + (2*wallThickness)
            ,-0.1,wallThickness])
			cube([3, slotWidth+(3*wallThickness), height-(2*wallThickness)], centre = false);

            // Security strap slot
        translate([wallThickness,wallThickness,-0.1])
			cube([slotDepth, slotWidth, height+0.2], centre = false);

			// Tube
		translate([tubeRadius + slotDepth + (wallThickness*2) +4
							,((slotWidth + (wallThickness*2))/2)
							,-0.1])
			cylinder(h=height + 0.2,r=tubeRadius, $fn=200);

			// Belt slot gap
		translate([-0.1,((slotWidth + 2*wallThickness)/2)-slotGap/2,-0.1])
			cube([wallThickness + 0.2, slotGap, height + 0.2], centre = false);

			// Tube slot gap
		translate([tubeWidth + slotDepth + 2.5*wallThickness - (tubeGap/2)
					,((slotWidth + 2*wallThickness)/2)-tubeGap/2
					,-0.1])
			cube([tubeGap, tubeGap, height + 0.2], centre = false);

			// Mounting holes
		if(numHoles>1){
			// Distribute the holes across the base
			delta = ((slotWidth + 2*wallThickness)/(numHoles))/2;
			for(y=[0:numHoles-1]){
				if(y==0){
					translate([-0.1,((slotWidth + 2*wallThickness)/(numHoles))/2,height/2])
						rotate([0,90,0]){
							cylinder(h=slotDepth + 2*wallThickness + tubeWidth
										,r=holeDiameter/2
										,$fn=200);
						}
				} else {
					translate([-0.1,(y*(slotWidth + 2*wallThickness)/(numHoles))+delta,height/2])
						rotate([0,90,0]){
							cylinder(h=slotDepth + 2*wallThickness + tubeWidth
										,r=holeDiameter/2
										,$fn=200);
						}
				}
			}
		} else {
			if(numHoles==1){
				// centre the hole right through the base
				translate([-0.1,((slotWidth + 2*wallThickness)/2),height/2])
					rotate([0,90,0]){
						cylinder(h=slotDepth + 2*wallThickness + tubeWidth
								,r=holeDiameter/2
								,$fn=200);
					}
			}
		}
	}

}

tripodclamp();

```


[User]
I'd like to get an OpenSCAD design for a replacement antenna mount for an old Multiplex RC transmitter, specifically the mc2020 or mc2010. I've got some specific requirements for it, and a pretty good idea of what I want it to look like, but I want to make sure it's parametric so I can adjust it easily for different hardware and variations.

Basically, it needs to be a snap-in replacement for the original antenna mount, but it needs to hold a standard 2.4 GHz antenna socket instead of the old telescopic antenna. I need a hole for the antenna socket itself, and a hex-shaped hole inside to hold the nut for the antenna socket when I tighten it down.

Here are the design considerations:

1.  **Main Body:** The general shape of the mount should be similar to the original, but with the necessary changes for the new antenna socket. It should have a sort of frame around the sides, and some connecting plates at the front. There should also be inner supporting pieces. The overall dimensions and shape should be easily adjustable using parameters.

2.  **Antenna Socket:**  It should have a central hole for a standard 2.4GHz antenna socket (I'll provide the dimensions). It needs the hex-shaped cavity to hold the socket's nut on the inside.

3.  **Optional Switch Mount:** I need an optional cutout below the antenna socket to mount a small slider switch. This is for selecting between different RF modules (e.g., Spektrum and Jeti). This part is optional, and the design should be able to be toggled between a version with the switch and one without.

4.  **Switch Cutout Details:** The switch cutout should have parameters for its width, height, and screw hole positions. The screw holes should be M2 sized, with adjustable hole diameter and spacing. The slider hole itself needs to have its dimensions adjustable too. I'd like the slider cutout to have small support ribs inside. And if the switch is enabled, it needs to have a cutout around the outside of the switch for lever access, and another cutout on the inside for the body of the switch.

5.  **Text:** If the switch is enabled, I need to have text on either side of the slider for labeling the positions, like "J" and "S." I want to be able to set that text as a parameter.

6.  **Support Structure:** I'd like an optional setting to have support structures printed into the switch cavity.

7.  **Libraries**: Please use the "write/Write.scad" library for text generation.

Could you design an OpenSCAD file (or set of files, if it makes sense) that includes all of this? Thanks.

[Assistant]
mc2020_antholder.scad:
```
//************** MC2020 Antenna Holder **************
//*    2.4GHz Antenna holder replacement instead of MPX part  *
//*            Henning Stöcklein   Version 28.11.2015                 *
//*          License: Free to use non-commercial only               *
//***********************************************

use <write/Write.scad>

//***************** User parametric data *************
// Put slider switch below antenna socket
Use_Switch = 1; // [0:w/o switch, 1:with slider switch]

// Text placed on right side of slider
Text_Right = "J" ;

// Text placed on left side of slider
Text_Left = "S" ;

// Switch Plate Cutout Width
switch_plate_w = 24 ; // [22:28]

// Switch Plate Cutout Height
switch_plate_h = 8 ; // [7:10]

// Switch M2 screw hole diameter
holedia = 1.2 ;

// Switch M2 screw hole distance
holedist = 19 ; // [15:22]

// Switch slider hole width
slider_width = 9.5 ;

// Switch slider hole height
slider_height = 4.2 ;

// Print Support Grid into switch hole
use_support = 1 ; // [0: w/o support, 1:with support]

//************** End of parametric data ***************

// Table for frame sides
framedata = [ [
[0		,	0		],
[0		,	11.5	],
[11.5	,	38		],
[18.0	,	36.5	],
[19.5 ,	34.0	],
[19.5	,	0		]],
[[0,1,2,3,4,5]]] ;

//****************************************************
// sidebody out of polygon chain
//****************************************************
module sideframe()
{
  scale ([1,1,1]) {
 	 linear_extrude(height=2.5) polygon(framedata[0],framedata[1]);
  }
}

//****************************************
// Combine all parts
//****************************************
module frame() {
 difference() {
  union() {
	translate ([0,0,-20-2.5]) sideframe();		// right side
	translate ([0,0, 20]) sideframe();			// left side

	translate ([-1,6.3, 0]) rotate ([0,0,-0.6])
	  cube ([4,12.6,40],center=true);	// lower front plane
	translate ([4.1,25, 0]) rotate ([0,0,-23.5])
	  cube ([3,28.3,40],center=true);								// front main plate
	translate ([6.3,24.0, 19.6]) rotate ([0,45,-23.5])
	  cube ([1.5,28,4],center=true);
	translate ([6.3,24.0, -19.6]) rotate ([0,-45,-23.5])
	  cube ([1.5,28,4],center=true);
	translate ([9.5,34, 0]) rotate ([0,0,-38])
	  cube ([2,8,40],center=true);
	translate ([12.6,36.2, 0]) rotate ([0,0,-13])
	  cube ([3,3,40],center=true);

	translate ([1,6, 19.5]) rotate ([0,45,0])
	  cube ([1.5,12,4],center=true);
	translate ([1,6, -19.5]) rotate ([0,-45,0])
	  cube ([1.5,12,4],center=true);

	translate([7.1,23,0]) rotate ([90,0,90-23.5])		// Inner wall for antenna socket
     cylinder (r1=15,r2=6.5,h=8.5,$fn=40,center=true) ;
  }

  translate ([7.8,38, 0]) cube ([6,3,40.05],center=true);
  translate ([9.86,39.2, 0]) rotate ([0,0,-24])
    cube ([4,4,40.05],center=true);
  translate ([14.5,36.2, 0]) rotate ([0,0,-40])
	 cube ([3,6,40-0.05],center=true);
 }
}

module socket() {
  cylinder (r=6.2/2, h=15, $fn=20) ;
  translate ([0,0,0]) cylinder (r=8/2, h=3.5, $fn=6) ;
  translate ([0,0,8.5]) cylinder (r=8/2, h=1.8, $fn=6) ;
}

// Cutout for Slider Switch (switch used to select different HF modules)
module switch() {
  if (use_support == 0)
    cube ([slider_width, slider_height, 8], center=true) ;					  // Slider is (9.1 / 3.8)

  // Cutout with 2 support ribs
  translate ([+slider_width/2-2.7/2, 0, 0]) cube ([2.7, slider_height, 8], center=true);
  translate ([-slider_width/2+2.7/2, 0, 0]) cube ([2.7, slider_height, 8], center=true);
  translate ([0,0,0]) cube ([3.1-(slider_width-9.5), slider_height, 8], center=true);

  translate ([0,0,-2]) cube ([switch_plate_w, switch_plate_h, 4], center=true) ; // Gehäuse (23.5 / 7.5)

/*
  // Screw holes M2 from outside
  translate ([-19/2,0,0]) cylinder (r=1, h=10, $fn=20, center=true);
  translate ([+19/2,0,0]) cylinder (r=1, h=10, $fn=20, center=true);
  // Chamfers for screw holes
  translate ([-19/2,0,2.4]) cylinder (r1=1, r2=2, h=1, $fn=20, center=true);
  translate ([+19/2,0,2.4]) cylinder (r1=1, r2=2, h=1, $fn=20, center=true);
*/

  // Blind holes for screws from inside
  translate ([-holedist/2,0,0]) cylinder (r=holedia/2, h=3.5, $fn=10, center=true);
  translate ([+holedist/2,0,0]) cylinder (r=holedia/2, h=3.5, $fn=10, center=true);
}

// Outside cutout around the switch
module switchprism_outer() {
  hull() {
    translate ([0,0,0]) cube ([34,9,0.1], center=true) ;
    translate ([0,0,2]) cube ([24,6,0.1], center=true) ;
  }
}

// Inside socket for the switch
module switchprism_inner() {
  hull() {
    translate ([0,0,0]) cube ([36,11,0.1], center=true) ;
    translate ([0,0,1.5]) cube ([27, 9, 0.1], center=true) ;
  }
}

//************************************
//*              Select here what to print
//************************************

//* Antenna holder itself
rotate ([90,0,0]) difference()
{
  union()
  {
    frame() ;
    if (Use_Switch == 1)
       translate ([1,6.8,0]) rotate ([0,90,0]) switchprism_inner() ;
  }

  translate([3,24.5,0]) rotate ([90,0,90-23.5])
     cylinder (r1=14,r2=6,h=5.5,$fn=40,center=true);			// Outer groove for socket
  translate([3,24.5,0]) rotate ([90,0,90-23.5])
     cylinder (r=6.5/2,h=14,$fn=20,center=true);			    // Antenna socket hole
  translate([10,21.5,0]) rotate ([90,0,90-23.5])
     cylinder (r=9.4/2,h=2.05,$fn=6,center=true);				// M6 Nut Hexagon hole
  translate ([0,0,0]) cube ([50,2.2,50], center=true) ;		// Cut ground plate

  if (Use_Switch == 1)
  {
     translate ([1.5,6.8,0]) rotate ([0,-90,0]) switch() ;                 // Subtract Switch Body
     translate ([-3,6.8,0]) rotate ([0,90,0]) switchprism_outer() ;    // Subtract Space for switch lever

     // Text "J" and  "S" below switch slider
     translate ([-1.3,6.8,8]) rotate ([0,-90,0]) write (Text_Right, t=1.5, h=4.2, center=true) ;
     translate ([-1.3,6.8,-8]) rotate ([0,-90,0]) write (Text_Left, t=1.5, h=4.2, center=true) ;
  }

  // Logo in basement
  //  translate ([1.5,7.5,0]) rotate ([0,90,0]) write ("HST 11.2015", t=1.5, h=4.1, center=true) ;
}

```


[User]
Hey, I'm trying to design a mold for a silicone adapter to connect tubing to soft robots and I'd love some help generating the OpenSCAD files. I have a few requirements and some dimensions in mind.

Basically, the adapter will have three main parts: a flange, a sleeve, and a hollow channel for the tubing. The flange is a flat disk that will be fused to the soft robot. The sleeve extends from the flange and this is where the tubing will be inserted. The hollow channel goes through both and allows for the tubing to run through the adapter into the robot.

Here are the specific dimensions I'm thinking of for the first version, but I'd like these to be easily changed later with parameters:

*   `FlangeHeight`: 7 mm
*   `FlangeRadius`: 15 mm
*   `SleeveHeight`: 15 mm
*   `TubingSize`: 6.35 mm (this is the *diameter* of the tubing)
*   `SleeveRadius`: TubingRadius + 4 mm
*   `OuterRadius`: FlangeRadius + 3.5 mm
*   `MoldHeight`: FlangeHeight + SleeveHeight + 5 mm

I'd like the design to be a mold, so the actual adapter will be the negative space left by the mold. The mold should be a cylinder with the `OuterRadius` and `MoldHeight`. The flange part of the mold should be created by subtracting a cylinder with `FlangeRadius` and `FlangeHeight` from the top of the mold. The sleeve section of the mold will be created by subtracting a cylinder with `SleeveRadius` and `SleeveHeight`, also from the top of the mold, on top of the flange cut. Finally, there needs to be a channel for the tubing. This channel should run all the way through the mold so that the tubing can be inserted through.

I was hoping to have it all in a single `.scad` file, but if it needs to be split up that's okay. I'm using OpenSCAD, but I don't need any external libraries. Could you generate this for me?

[Assistant]
Adapter.scad:
```
FlangeHeight = 7;
FlangeRadius = 15;
SleeveHeight = 15;
TubingSize = 6.35;
TubingRadius = TubingSize / 2;
SleeveRadius = TubingRadius + 4;
OuterRadius = FlangeRadius + 3.5;
MoldHeight = FlangeHeight + SleeveHeight + 5;
difference() {
cylinder(MoldHeight,OuterRadius,OuterRadius,0);
union() {
translate([0,0,MoldHeight - SleeveHeight - FlangeHeight]){
difference() {
cylinder(SleeveHeight,SleeveRadius,SleeveRadius,0);
    cylinder(SleeveHeight,TubingRadius,TubingRadius,0);
}
}
difference() {
translate([0,0,MoldHeight - FlangeHeight]){
cylinder(FlangeHeight,FlangeRadius,FlangeRadius,0);
}
cylinder(90,TubingRadius,TubingRadius,0);
}
}
}
```


[User]
Okay, I'm looking to design a small, modular table using OpenSCAD. I want it to have a few key features:

First, the legs will be built using a modified version of the board_holder module I have. Instead of two intersecting cubes, I'd like each leg to consist of two boards, maybe 30mm wide, that interlock at a right angle. The height of the legs will be adjustable, and I'd also like to have the thickness of the boards used to be parametric. I'd like to be able to set the board width and thickness, and have these parameters used throughout the design.

Second, the table top will be made up of multiple interlocking boards, similar to the legs, but in a larger scale. I want to be able to specify the length and width of the table, and have it generate as a grid of boards, all the same thickness and width as the leg boards. I want the boards of the table to intersect like the legs, such that the edges are flush.

Finally, I want to be able to insert some bottle holders in the table top, using the bottom module. I'd like to specify the radius and size (depth) of these holders. The position of these bottle holders should be set by a list of coordinates, and I'd like to be able to specify how many bottle holders I want.

I'd also like the design to be easily customizable through parameters. Ideally, I'd like to be able to modify the height of the table, the width/thickness of all the boards, the overall length and width of the table, the number and position of the bottle holders, and the diameter and depth of these holders.

I think this should be pretty easily done with OpenSCAD's module system. I'm not really concerned with fancy rendering or anything. I don't need any included library modules for this, just the basic OpenSCAD functionality and some math.

[Assistant]
Joint_v1.scad:
```

// Adjust the thickness of the piece
height=2; // min/max: [2:50]

//// RENDER

//// MODULES

module board_holder (lenght, width, height) {
     union () {
        cube([lenght,width,height]);
        cube([width,lenght,height]);
     }

    translate ([0,0,height+10]) {
        union () {
            cube([lenght,width,height]);
            cube([width,lenght,height]);
         }
     }
    union () {
        translate ([0,0,height])
        cube ([lenght,height,height+10]);
        translate ([0,0,height])
        cube ([height,lenght,height+10]);
    }
}

module bottom (radius, size) {
    $fn=100;
    translate ([radius+5,radius+5,-size]){
        difference () {
            cylinder (r=radius,h=size);
            cylinder (r=radius-2,h=height);
        }
    }
}

```


[User]
I'd like a parametric OpenSCAD design for a box with a rectangular cutout running through the top portion. The box should be defined by three parameters: width, length, and height. The cutout should be centered on the top face, going through the top 7/8 of the height. It should also be a little bit smaller than the base of the box, say one unit smaller in both width and length.

The parameters for width and length should have a minimum value of 5 and a maximum value of 100. The parameter for height should have a minimum of 10 and a maximum of 250.

[Assistant]
TEST.scad:
```

width=20; min/max: [5:100]

lenght=20; min/max: [5:100]

height=30; min/max: [10:250]

module box (width,lenght,height) {
    difference () {
        cube ([width,lenght,height]);
        translate ([width/width,lenght/lenght,height/8])
            cube ([width-2,lenght-2,height]);
    }
}

```


[User]
Hey there, I'm looking to design a custom magic wand handle, and I think OpenSCAD would be perfect for this. I've seen some examples where the handle has a twisted texture, and I really like that look.

Ideally, the design should have a few customizable parameters:
*   **`opening_diameter`**: The diameter of the hole that the wooden dowel will fit into (I'm thinking something around 10.8mm to start).
*   **`handle_length`**: The overall length of the handle (100mm sounds good to me, but I'd like to adjust this).
*   **`twist_factor`**:  A value to control the twist on the handle (maybe in the range of 1 to 15).
*   **`endcap_thickness`**: The thickness of the rims at the top and bottom of the handle. I need to be able to control the overhang of those endcaps too (I think an overhang of twice the thickness would work well).

The handle itself will need to be hollow to accommodate the dowel. I'd like a rounded look, so the main body should be a cylinder and the endcaps should be toroids.  The twist should be applied to the cylindrical body itself, and it's fine to use `linear_extrude` to make the handle's body from a square shape with the twisting applied. I'd like for the extrusion to be hollow as well. There should be a buffer of 0.5mm around the inner cylinder for tolerances.

Could you generate a parametric OpenSCAD file (or set of files if needed) for this design? I don't need any specific libraries, just the standard OpenSCAD functionality should be enough. Thanks!

[Assistant]
magic_wand_handle.scad:
```
// Magic Wand Handle (Thingiverse Customizer supported)
// Increase resolution (*1 to hide)
$fn=(100 * 1);

// Following variables are visible in Customizer
// (.5 mm will be added as a buffer)
opening_diameter = 10.8;
handle_length = 100;
twist_factor = 2; // [1:15]
endcap_thickness = 2; // [1:5]

// Hidden from Customizer
handle_od = (opening_diameter + 1.5);
endcap_overhang = (2 * 1);
buff = (.5 * 1);

module vertical_cylinder(dia)
{
    translate([0, 0, endcap_thickness])
        cylinder(h=(handle_length + endcap_thickness), r=(dia / 2), center=true);
}

module twist_texture(twist)
{
    linear_extrude(height = handle_length, center = true, twist = twist)
        square((handle_od - 2), center=true);
}

module end_rim(offset)
{
    translate([0, 0, offset])
        cylinder(h=endcap_thickness, r=((handle_od + endcap_overhang) / 2), center=true);
}

difference()
{
    union()
    {
        // Hollow out center
        cylinder(h=handle_length, r=(handle_od / 2), center=true);

        // Render Handle
        twist_texture((twist_factor * 100));
        twist_texture(-((twist_factor * 100) + ((twist_factor * 100) / 4)));

        // Top rim
        end_rim((handle_length / 2));

        // Bottom rim
        end_rim(-(handle_length / 2));
    }

    // Hollow out center
    vertical_cylinder((opening_diameter + buff));
}
```


[User]
Hey, I'm looking to design a smartphone microscope attachment, and I'm hoping you can help me generate the OpenSCAD files for it. I've got a good idea of the shape I want, sort of a clip-on design, and I've already made a prototype using some basic shapes, which I'll describe in more detail.

The basic idea is to create a clip that attaches to a smartphone and holds a small lens from a laser pointer or CD player at a specific distance. I've got three main modules I need: a `semi_circle_shell`, a `curve_shell`, and a `wave`.

The `semi_circle_shell` module creates a semi-circular shell shape with a specified radius, shell thickness, and shell height. It's basically a hollowed out quarter of a cylinder. The `curve_shell` is similar but creates more of a curve shape using the `semi_circle_shell`, and adds a masking element to the shape. Finally, the `wave` module combines two different `curve_shell` modules, one of which is mirrored to create a wave-like shape that serves as the main structural element of the clip.

The main `clip` module then uses the wave module to create the overall shape of the clip and also adds a mounting point for the lens itself. It's important that the user can adjust `lens_distance`, `lens_radius`, and `phone_thickness` as parameters. The `clip` module also uses the difference of a cylinder to form the lens mounting.

I’m not using any libraries but you should use standard OpenSCAD commands. Could you generate all the files for this?

Here's a summary of the parameters I'd like to be adjustable:

*   `lens_distance`: Distance between the lens and the smartphone.
*   `lens_radius`: Radius of the lens.
*   `phone_thinkness`: Thickness of the smartphone.
*  `shell_thickness`: Thickness of the main structure.
*  `shell_height`: Height of the structure

I'm looking forward to what you can come up with!

[Assistant]
smartphone_microscope.scad:
```
lens_distance = 35.5;
lens_radius = 2.5;
phone_thinkness = 7;

clip(lens_distance, lens_radius, phone_thinkness);

module semi_circle_shell(radius, shell_thickness = 2, shell_height = 15) {
    difference() {
        rotate_extrude(convexity = 10, $fn=72)
            translate([radius, 0, 0])
                square([shell_thickness, shell_height]);

        outer_radius = radius + shell_thickness;

        translate([-outer_radius, -outer_radius, -1])
            cube([outer_radius * 2, outer_radius, shell_height + 2]);
    }
}

module curve_shell(radius, shell_thickness = 2,  shell_height = 15) {
    mask_thickness = radius * 0.5;

    translate([0, -mask_thickness, 0]) difference() {
        semi_circle_shell(radius, shell_thickness, shell_height);

        width = radius + shell_thickness;

        translate([-width, 0, -shell_thickness / 2])
            cube([width * 2, mask_thickness, shell_height + shell_thickness]);
    }
}

module wave(l1, l2, shell_thickness = 2, shell_height = 15) {
    square_root_of_3 = 1.732050807568877;
    r1 = 2 * l1 / square_root_of_3;
    r2 = 2 * l2 / square_root_of_3;

    translate([l2 + shell_thickness, 0, 0])
        curve_shell(r2, shell_thickness, shell_height);

    mirror([0, 1, 0])
        translate([l1 + 2 * (shell_thickness + l2) + 0.2, 0, 0])
            curve_shell(r1, shell_thickness, shell_height);
}

module clip(lens_distance, lens_radius, phone_thickness, shell_thickness = 2, shell_height = 15) {
    l1 = (lens_distance - shell_thickness) / 7;
    l2 = 3 * l1;

    square_root_of_3 = 1.732050807568877;
    r1 = 2 * l1 / square_root_of_3;

    y_offset = r1 * 0.25 + shell_thickness + phone_thickness;

    difference() {
        union() {
           wave(l1, l2, shell_thickness, shell_height);

           translate([0, -(phone_thickness + r1 * 0.25 + 2 * shell_thickness), 0])
               cube([(l1 + l2) * 2 + shell_thickness * 4, shell_thickness, shell_height]);

           translate([0, -y_offset, 0]) cube([shell_thickness, y_offset, shell_height]);
        }

        translate([lens_distance + shell_thickness, -y_offset + 2, shell_height / 2])
            rotate([90, 0, 0])
                cylinder(r=lens_radius, h=6, $fn=72);
    }
}

```


[User]
Hey there, I'm looking to get an OpenSCAD design for a phone holder, specifically one that mounts to a cylindrical bar like on a bicycle. I've seen some designs out there, but I need one that's highly customizable.

Here's what I'm thinking: I need to be able to adjust the phone's dimensions (length, width, and thickness), the diameter of the bar it's mounted on, and the distance the phone sits away from the bar (the "holder height"). I'm also after an offset for the phone along the long axis - basically, I need to be able to slide the phone up or down relative to the holder's central axis, which is super important since power buttons and such aren't always in the same place.

The design I'm picturing is similar to the one in the provided SCAD code, essentially a vertical piece that the phone slots into and a horizontal part that clamps to the bar, with a sort of rounded or beveled design so that edges are not too sharp. The phone is supposed to be held pretty securely. It should be easy to print, and I need the customizability to be able to tweak it for different phones. I also need the ability to set a value for the `$fs` variable.

I'm not too familiar with OpenSCAD, but I've seen some mention of libraries that might be helpful. I think I'd like to use the `BOSL2` library for its great shape building tools and ease of design. I would also like to be able to specify the filename in a parameter within the main `.scad` file (using the `str()` function), so that I can create STL files with the dimensions of the phone in the name of the file.

Could you help me create an OpenSCAD design based on these parameters? I’m looking for a set of files or one file, I don’t really mind, that would work using the BOSL2 library.

[Assistant]
Phone_Holder_Lumia640.scad:
```
// Depending on your printer, you should add an extra 1 to 2 mm.
Phone_Length=143;
// Depending on your printer, you should add an extra 1 to 2 mm.
Phone_Width=74;
// Depending on your printer, you should add an extra 1 to 2 mm.
Phone_Thickness = 10;

// Diameter of the bar where the holder is to be mounted.
Handle_Bar_Diameter = 36;
// Distance from the handle bar to the back of the phone. A smaller number will give a lower profile.
Holder_Height = 17; // [11:17]
// Offset from the center on the vertical part
Vertical_Offset = -15;

/* [Hidden] */
$fs = 1;

module copy_mirror(vec=[0,1,0]) {
 union() {
  children();
  mirror(vec) children();
 }
};

module rounded_corner(vec=[0,0,0],rot=0) {
 translate(vec) rotate([0,0,rot]) difference(){
  intersection(){
   cylinder(r=6.5,h=5);
   translate([-6.5,0,0]) cube([6.5,6.5,5]);
  };
  cylinder(r=1.5,h=5);
 };
};

// Vertical Piece
//translate([2.5,0,0]) rotate([0,-90,0]) difference(){
difference(){
 union(){
  translate([23,Phone_Length/2+2.5,0]) cylinder(r=2.5,h=5);
  translate([18.5,Phone_Length/2,0]) cube([4.5,5,5]);
  copy_mirror([0,1,0]) rounded_corner([18.5,Phone_Length/2-1.5,0]);
  translate([12,-Phone_Length/2+1.5,0]) cube([5,Phone_Length-3,5]);
  translate([18.5,-Phone_Length/2-5,0]) cube([Phone_Thickness-1.5,5,5]);
  translate([17+Phone_Thickness,-Phone_Length/2-2.5,0]) cylinder(r=2.5,h=5);
  linear_extrude(height=5) polygon([[12,-39+Vertical_Offset],[12,39+Vertical_Offset],[10.3923,33+Vertical_Offset],[0,15+Vertical_Offset],[0,-15+Vertical_Offset],[10.3923,-33+Vertical_Offset]]);
 };
 translate([0, Vertical_Offset, 0]) copy_mirror([0,1,0]) translate([0,39,0]) cylinder(r=12,h=5);
 translate([0, Vertical_Offset, 0]) copy_mirror([0,1,0]) translate([9,12.5,0]) cube([5,10,5]);
 translate([17-Holder_Height,-5.5/2 + Vertical_Offset,0]) cube([Holder_Height/2+0.2,5.5,5]);
 translate([-Holder_Height,-30,0]) cube([17,60,5]);
};

// Horizontal Piece
//translate([0,2.5,0]) rotate([90,0,0]) copy_mirror([1,0,0]) difference(){
translate([-30,Vertical_Offset,0]) rotate([0,0,-90]) copy_mirror([1,0,0]) difference(){
 union(){
  linear_extrude(height=5) polygon([[0,-3],[10,-3],[14.6768,10.0145],[17.5,12],[Phone_Width/2-1.5,12],[Phone_Width/2-1.5,17],[0,17]]);
  rounded_corner([Phone_Width/2-1.5,18.5,0],180);
  translate([Phone_Width/2,18.5,0]) cube([5,Phone_Thickness-3,5]);
  rounded_corner([Phone_Width/2-1.5,17+Phone_Thickness-1.5,0],-90);
  translate([Phone_Width/2-1.5,17+Phone_Thickness+1.5,0]) cylinder(r=1.5,h=5);
  translate([Phone_Width/2-1.5,17+Phone_Thickness+5-1.5,0]) cylinder(r=1.5,h=5);
  translate([Phone_Width/2-3,17+Phone_Thickness+1.5,0]) cube([1.5,2,5]);
  translate([5.5/2,17,5/2]) rotate([90,0,0]) linear_extrude(height=20) polygon([[0,0],[5,0],[0,5]]);
 };
 translate([17.5,9,0]) cylinder(r=3,h=5);
 translate([0,-Handle_Bar_Diameter/2-Holder_Height+17,0]) cylinder(r=Handle_Bar_Diameter/2,h=10);
 translate([-5.5/2,17-(Holder_Height/2+0.2),0]) cube([5.5,Holder_Height/2+0.2,5]);
};

```


[User]
I'd like to create a 3D model that projects a 2D image onto the surface of a sphere. I've attached a sample .scad file that does this, but it's not parametric enough for my needs. Specifically, the `image` array is hardcoded, and it relies on a specific projection, plus the final output is more of a faceted surface than a smooth one. I'd like to be able to easily specify the image, the projection, and the level of smoothing of the final model.

My basic requirements are:

1.  **Image Input:** The image should be loaded from an external file, ideally a standard image format like PNG, JPG, or even a simple text file where each pixel is represented as a 0 or 1. This way, I don't have to manually create the array as in the example file.
2.  **Projection Choice:** Instead of only having that specific projection function, I want to be able to choose between several common projections such as:
    *   The current one from the example (a stereographic projection, I believe).
    *   A simple cylindrical projection.
    *   A Mercator projection.
    *   Perhaps even a simple equirectangular projection.
3.  **Smoothness Control:** I'd like to control the smoothness of the model. The example uses a simple polyhedron, but I'd prefer something that results in a smoother, more curved surface. Perhaps I should be using something like `surface` with a higher resolution grid, or `linear_extrude` with more segments.
4.  **Parametric Control:**  I want to be able to easily adjust the outer and inner radius, the size of the image being projected, and any parameters specific to the projection being used (e.g., the latitude and longitude range for Mercator)

Could you generate a set of OpenSCAD files that can achieve this? Please make sure to use a modular approach, so that it's easy to change and expand. I think it would be good to use the `BOSL2` library for general utility and data structures.

[Assistant]
HQmap.scad:
```
outer_radius=100; //[30:200]
inner_radius=98; //[29:199]

image=[0.000,0.000,0000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,1.000,0.000,1.000,0.000,1.000,0.000,1.000,0.000,1.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,1.000,0.000,1.000,0.000,1.000,0.000,1.000,0.000,1.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,1.000,0.000,1.000,0.000,1.000,0.000,1.000,0.000,1.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,1.000,0.000,1.000,0.000,1.000,0.000,1.000,0.000,1.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,1.000,0.000,1.000,0.000,1.000,0.000,1.000,0.000,1.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000]; // [image_array:2000x2000]

size=sqrt(len(image));
hsize=size/2;
qsize=size/4;

for(x=[0:size-1]) {
	for(y=[0:size-1]) {
		if(getPoint(x,y)) {
			drawPoint(x,y);
		}
	}
}

module drawPoint(x,y) {
	xt=x-hsize;
	yt=y-hsize;
	p1=project((xt-0.5)/qsize,(yt-0.5)/qsize);
	p2=project((xt-0.5)/qsize,(yt+0.5)/qsize);
	p3=project((xt+0.5)/qsize,(yt+0.5)/qsize);
	p4=project((xt+0.5)/qsize,(yt-0.5)/qsize);
	p1i=p1*inner_radius;
	p2i=p2*inner_radius;
	p3i=p3*inner_radius;
	p4i=p4*inner_radius;
	p1o=p1*outer_radius;
	p2o=p2*outer_radius;
	p3o=p3*outer_radius;
	p4o=p4*outer_radius;
	polyhedron(points=[p1i,p2i,p3i,p4i,p1o,p2o,p3o,p4o],
		triangles=[[0,1,2],[0,2,3],[4,7,5],[7,6,5]]);
	if(x==0||!getPoint(x-1,y)) {
		polyhedron(points=[p1i,p1o,p2i,p2o],triangles=[[0,1,2],[1,3,2]]);
	}
	if(x==size-1||!getPoint(x+1,y)) {
		polyhedron(points=[p3i,p3o,p4i,p4o],triangles=[[0,1,2],[1,3,2]]);
	}
	if(y==0||!getPoint(x,y-1)) {
		polyhedron(points=[p4i,p4o,p1i,p1o],triangles=[[0,1,2],[1,3,2]]);
	}
	if(y==size-1||!getPoint(x,y+1)) {
		polyhedron(points=[p2i,p2o,p3i,p3o],triangles=[[0,1,2],[1,3,2]]);
	}
}

function project(x,y)=[2*x/(1+x*x+y*y),2*y/(1+x*x+y*y),(x*x+y*y-1)/(1+x*x+y*y)];
function getPoint(x,y)=image[y*size+x]<0.5;

```


[User]
I want to create a 3D model that maps a 2D image onto the surface of a sphere, effectively making a sort of distorted globe. I'm thinking of using OpenSCAD for this.

The core idea is this: I'll provide a square 2D image, essentially a grid of pixel data where each pixel will be either "on" or "off" (represented by a 0 or a 1, or anything less than 0.5 counts as "off" and equal or greater is "on"). Each "on" pixel from the image should be rendered as a small rectangular prism that projects out of the surface of a base sphere. The corners of these prisms would be based on the mapping of the corners of the "pixel" square to the surface of a sphere using a stereographic projection.

To clarify further, I want the base sphere to be defined by two radii - an *inner radius* and an *outer radius*. The prisms representing pixels should extend from the inner to the outer radius.  The base sphere should have the center at (0, 0, 0)

I should also be able to control the size of the image, and it should always be a square. Ideally I'd like to use the standard math library to calculate the size of the image rather than having to manually enter it as a variable.

Additionally, it should be relatively easy to control the inner and outer radius of the sphere.

Finally, each "pixel" prism should be connected to its neighbors where possible. If two pixels are both "on", and neighbors, the prisms they represent should be connected along the edges where they touch. This should create a smooth continuous surface of protrusions on the sphere, rather than just a series of disconnected blocks. If a pixel is next to a pixel that is "off" it should have its outer face drawn for that face.

Can you help me generate the OpenSCAD file or files needed to do this?

[Assistant]
HQmap.scad:
```
outer_radius=100; //[30:200]
inner_radius=98; //[29:199]

image=[0.000,0.000,0000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,1.000,0.000,1.000,0.000,1.000,0.000,1.000,0.000,1.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,1.000,0.000,1.000,0.000,1.000,0.000,1.000,0.000,1.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,1.000,0.000,1.000,0.000,1.000,0.000,1.000,0.000,1.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,1.000,0.000,1.000,0.000,1.000,0.000,1.000,0.000,1.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,1.000,0.000,1.000,0.000,1.000,0.000,1.000,0.000,1.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000]; // [image_array:5000x5000]

size=sqrt(len(image));
hsize=size/2;
qsize=size/4;

for(x=[0:size-1]) {
	for(y=[0:size-1]) {
		if(getPoint(x,y)) {
			drawPoint(x,y);
		}
	}
}

module drawPoint(x,y) {
	xt=x-hsize;
	yt=y-hsize;
	p1=project((xt-0.5)/qsize,(yt-0.5)/qsize);
	p2=project((xt-0.5)/qsize,(yt+0.5)/qsize);
	p3=project((xt+0.5)/qsize,(yt+0.5)/qsize);
	p4=project((xt+0.5)/qsize,(yt-0.5)/qsize);
	p1i=p1*inner_radius;
	p2i=p2*inner_radius;
	p3i=p3*inner_radius;
	p4i=p4*inner_radius;
	p1o=p1*outer_radius;
	p2o=p2*outer_radius;
	p3o=p3*outer_radius;
	p4o=p4*outer_radius;
	polyhedron(points=[p1i,p2i,p3i,p4i,p1o,p2o,p3o,p4o],
		triangles=[[0,1,2],[0,2,3],[4,7,5],[7,6,5]]);
	if(x==0||!getPoint(x-1,y)) {
		polyhedron(points=[p1i,p1o,p2i,p2o],triangles=[[0,1,2],[1,3,2]]);
	}
	if(x==size-1||!getPoint(x+1,y)) {
		polyhedron(points=[p3i,p3o,p4i,p4o],triangles=[[0,1,2],[1,3,2]]);
	}
	if(y==0||!getPoint(x,y-1)) {
		polyhedron(points=[p4i,p4o,p1i,p1o],triangles=[[0,1,2],[1,3,2]]);
	}
	if(y==size-1||!getPoint(x,y+1)) {
		polyhedron(points=[p2i,p2o,p3i,p3o],triangles=[[0,1,2],[1,3,2]]);
	}
}

function project(x,y)=[2*x/(1+x*x+y*y),2*y/(1+x*x+y*y),(x*x+y*y-1)/(1+x*x+y*y)];
function getPoint(x,y)=image[y*size+x]<0.5;

```


[User]
I'm looking to create a parametric filament holder for my Prusa i3, designed to be a significant improvement over the stock holder. I'm tired of wrestling with it every time I change filament.

Here's what I'm envisioning, with some specific dimensions I'd like to be able to control:

*   **Bearings:** The design should accommodate standard 608 bearings (or similar). I need to be able to adjust the outer diameter, inner diameter (shaft size), and height of the bearing via parameters. The design should include a small spacer around the shaft of each bearing. This spacer should also have its diameter and depth be parametrizable.
*   **Bearing Placement:** I want two bearings to support the filament roll, with the distance between them also being a customizable parameter.
*   **Base Plates:** The bearings should be mounted onto two separate, identical base plates. The depth of these plates needs to be a parameter. The plates should have rounded edges for aesthetic purposes and to make them less likely to snag on anything.
*   **Frame Clamp:** The holder needs a frame clamp to attach to the printer's frame. The height and width of this clamp should be adjustable, as well as the depth of the frame it's designed to fit on.
*   **Pulleys:** I'd like to include a pulley on each bearing, which will make it easier for the filament to be pulled. The diameter of the pulley should be automatically calculated from the bearing dimensions.

Here's a more detailed breakdown of the parameters I would need to adjust. I've provided suggested default values in the provided code.

*   `bearingOuterDiameter`: (e.g. 22.2)
*   `bearingInnerDiameter`: (e.g. 8)
*   `bearingHeight`: (e.g. 7)
*   `bearingSpacerDiameter`: (e.g. 3, added to the bearingInnerDiameter)
*   `bearingSpacerDepth`: (e.g. 0.5)
*   `bearingsDistance`: (e.g. 100, distance between the centers of the bearings)
*   `plateDepth`: (e.g. 3.5)
*   `frameClampHeight`: (e.g. 30)
*   `frameClampWidth`: (e.g. 40)
*    `frameDepth`: (e.g. 6)
*   `cornerRadius`: (e.g. 5, for rounded edges)

The design should automatically calculate derived dimensions such as the pulley diameter, the width of the plate, the height of bearing knobs, etc.

I'd like this to be done using OpenSCAD, and would expect it to use the `hull` and `linear_extrude` functions, alongside `cylinder`, `cube` and `difference` primitives. I do not expect any use of libraries (e.g. MCAD, BOSL, etc.).

It would be ideal if the code was well-organized and commented, and I'd prefer two separate plate modules to aid in making sure each is laid out correctly (one called `plate1` and one called `plate2`).

[Assistant]
role_holder.scad:
```

// outer diameter of the bearing
bearingOuterDiameter = 22.2;  // [10:0.1:50]

// inner (shaft) diameter of the bearing
bearingInnerDiameter = 8; // [5:0.1:15]

// height of bearing (add 0.2-0.5 according to your printer)
bearingHeight = 7; // [5:0.1:30]

// bearing spacer diameter (addition to bearingInnerDiameter)
bearingSpacerDiameter = 3; // [0.1:0.1:20]

// bearing spacer depth
bearingSpacerDepth = 0.5; // [0:0.1:3]

// distance between bearings
bearingsDistance = 100; // [70:125]

// depth of plate(s)
plateDepth = 3.5; // [2:0.1:15]

// height of frame clamp
frameClampHeight = 30; // [10:50]

// width of frame clamp
frameClampWidth = 40; // [10:60]

// depth of Prusa i3 (or similar printer) frame
frameDepth = 6; // [4:0.1:10]

/* [hidden] */
cornerRadius = 5;
pulleyDiameter = bearingOuterDiameter + bearingHeight + 1;
plateWidth = pulleyDiameter + cornerRadius;
knobY = plateWidth - (bearingInnerDiameter + bearingSpacerDiameter) / 2;
endX = (bearingsDistance + pulleyDiameter);
centerX = endX / 2;
leftKnobX = pulleyDiameter / 2;
rightKnobX = bearingsDistance + pulleyDiameter / 2;
fixY = cornerRadius / 2;
leftFixX = cornerRadius / 2;
rightFixX = endX - cornerRadius / 2;

module roundedCube (size, radius) {
  x = size[0];
  y = size[1];
  z = size[2];

  translate ([x/2,y/2,0])
  linear_extrude (height=z)
  hull() {
    translate([(-x/2)+(radius/2), (-y/2)+(radius/2), 0]) circle(r=radius);
    translate([(x/2)-(radius/2), (-y/2)+(radius/2), 0]) circle(r=radius);
    translate([(-x/2)+(radius/2), (y/2)-(radius/2), 0]) circle(r=radius);
    translate([(x/2)-(radius/2), (y/2)-(radius/2), 0]) circle(r=radius);
  }
}

module pulley() {
  difference() {
    cylinder (d=pulleyDiameter, h=bearingHeight);
    cylinder (d=bearingOuterDiameter, h=bearingHeight);

    translate ([0, 0, bearingHeight/2]) rotate_extrude (convexity = 10) translate ([pulleyDiameter/2, 0,0]) circle (d=bearingHeight - 2);
  }
}

module bearingKnob() {
  union() {
    cylinder (h=bearingHeight+plateDepth/2+bearingSpacerDepth,d=bearingInnerDiameter);
    //cylinder (h=bearingHeight, d=bearingOuterDiameter); // test bearing
  }
}

module bearingSpacer() {
  difference() {
    cylinder (h=bearingSpacerDepth, d=bearingInnerDiameter+bearingSpacerDiameter);
    bearingKnob();
  }
}

module bearingKnobWithSpacer() {
  union() {
    bearingKnob();
    bearingSpacer();
  }
}

module clamp (depth=plateDepth) {
  translate ([(frameClampWidth + frameDepth + 2) / -2, 0, 0])
  linear_extrude (height=depth)
  difference() {
    polygon (points=[[0,frameClampHeight], [frameClampWidth + frameDepth + 2, frameClampHeight], [frameClampWidth/2 + frameDepth + 2, 0], [frameClampWidth/2, 0]]);

    center = (frameClampWidth + frameDepth + 2) / 2;

    polygon (points=[[center - frameDepth / 2, 0], [center + frameDepth / 2, 0], [center + frameDepth / 2, frameClampHeight], [center - frameDepth / 2, frameClampHeight]]);
  }
}

module plate1() {
  difference() {
    union() {
      roundedCube ([endX, cornerRadius, plateDepth], cornerRadius);
      hull() {
        roundedCube ([pulleyDiameter, cornerRadius, plateDepth], cornerRadius);
        translate ([pulleyDiameter/2, knobY, 0]) cylinder (d=bearingOuterDiameter, h=plateDepth);
      }

      hull() {
        translate ([bearingsDistance, 0, 0]) roundedCube ([pulleyDiameter, cornerRadius, plateDepth], cornerRadius);
        translate ([rightKnobX, knobY, 0]) cylinder (d=bearingOuterDiameter, h=plateDepth);
      }

      translate ([leftKnobX, knobY, plateDepth]) bearingKnobWithSpacer();
      translate ([rightKnobX, knobY, plateDepth]) bearingKnobWithSpacer();

      translate ([0,0,plateDepth]) {
        hull() {
          translate ([cornerRadius/2,cornerRadius/2,0]) cylinder (h=bearingHeight+2*bearingSpacerDepth, d=cornerRadius*2);
          translate ([bearingsDistance + pulleyDiameter - cornerRadius/2, cornerRadius/2, 0]) cylinder (h=bearingHeight+2*bearingSpacerDepth, d=cornerRadius*2);
        }
      }

      translate ([centerX, - frameClampHeight - cornerRadius/2 + 0.005, 0]) clamp (depth=plateDepth*2 + bearingHeight + bearingSpacerDepth);
    }

    translate ([leftFixX,fixY,plateDepth]) cylinder (h=bearingHeight+2*bearingSpacerDepth, d=cornerRadius);
    translate ([centerX,fixY,plateDepth]) cylinder (h=bearingHeight+2*bearingSpacerDepth, d=cornerRadius);
    translate ([rightFixX,fixY,plateDepth]) cylinder (h=bearingHeight + 2*bearingSpacerDepth, d=cornerRadius);
  }
}

module plate2() {
  union() {
    difference() {
      union() {
        roundedCube ([endX, cornerRadius, plateDepth], cornerRadius);
        hull() {
          roundedCube ([pulleyDiameter, cornerRadius, plateDepth], cornerRadius);
          translate ([leftKnobX, knobY, 0]) cylinder (d=bearingOuterDiameter, h=plateDepth);
        }

        hull() {
          translate ([bearingsDistance, 0, 0]) roundedCube ([pulleyDiameter, cornerRadius, plateDepth], cornerRadius);
          translate ([rightKnobX, knobY, 0]) cylinder (d=bearingOuterDiameter, h=plateDepth);
        }
      }

      translate ([leftKnobX, knobY, plateDepth / 2]) bearingKnob();
      translate ([rightKnobX, knobY, plateDepth / 2]) bearingKnob();
    }

    translate ([leftKnobX, knobY, plateDepth]) bearingSpacer();
    translate ([rightKnobX, knobY, plateDepth]) bearingSpacer();

    translate ([leftFixX, fixY,plateDepth]) cylinder (h=bearingHeight + 2*bearingSpacerDepth, d=cornerRadius);
    translate ([centerX,fixY,plateDepth]) cylinder (h=bearingHeight + 2*bearingSpacerDepth, d=cornerRadius);
    translate ([rightFixX,fixY,plateDepth]) cylinder (h=bearingHeight + 2*bearingSpacerDepth, d=cornerRadius);
  }
}

plate1();
translate ([0, plateWidth + cornerRadius + 10, 0]) plate2();
translate ([leftKnobX, -pulleyDiameter, 0]) pulley();
translate ([rightKnobX, -pulleyDiameter, 0]) pulley();

/*
//test pulleys on knobs
translate ([leftKnobX, knobY, plateDepth + bearingSpacerDepth]) pulley();
translate ([rightKnobX, knobY, plateDepth + bearingSpacerDepth]) pulley();
*/

```


[User]
I need a parametric OpenSCAD design for a camera adapter that will attach to a microscope. I've got a picture of something similar [here](https://flic.kr/p/BFR4RW) and a basic SCAD file I was messing around with. I'm not expecting you to use the exact same dimensions as that example, I just want a parametric version of the basic idea that can be customized easily.

Specifically, the adapter should have the following features:

*   **Main Body:** A cylindrical body with a stepped profile. It should have at least three sections: a smaller cylinder at the base to fit inside the microscope opening, then an increasing step up to a wider cylinder, and then maybe another wider step up to a flange with a flat top.
*   **Microscope Connection:** The smaller cylinder that goes into the microscope needs to be configurable by diameter and height.
*   **Camera Connection:** The flange at the top should have a diameter and thickness parameter that can be adjusted, plus the diameter of any interior hole in the flange should be configurable. Also, this hole needs mounting holes for screws in it to secure the camera.
*   **Hole Pattern:** I'd like to specify the diameter of the bolt circle for those screw holes, as well as the number of holes, and the size of those bolt holes. I'm going to use metric bolts.

It would be super helpful if the entire design was parameterized so I can easily tweak the dimensions to fit different scopes and cameras. Can you do that for me? I don't really have a strong preference on which libraries to use.

[Assistant]
cam_adapter.scad:
```
$fn=32;

module template(){
	import("camera_microscope_adapter_2_holes_repaired.stl");
} //template();

module adapter(){
difference(){
	union(){
		translate([0,0,2]) cylinder(h=10, d=34, center=true);
		translate([0,0,7]) cylinder(h=3,r1=17,r2=21.5,center=false);
		translate([0,0,10]) cylinder(h=20,r=25,center=false, $fn=6);
	}
	translate([0,0,3]) cylinder(h=15, d=30, center=true);
	translate([0,0,10]) cylinder(h=21,r=20,center=false, $fn=6);
	for(i=[0:60:360]){
	rotate([0,0,i]) M3();
}
}
} adapter();

module M3(){
	rotate([0,0,30])
	translate([16.5,00,20])
	rotate([0,90,0])
	union() {
		translate([0,0,4]) cylinder(h=10, d=3.5, center=false);
		cylinder(h=4, d=8, center=false,$fn=6);
	}
} //M3();

```


[User]
Hi, I'm working on a project to retrofit the gimbals from an old Multiplex Profi mc transmitter into a more modern system, specifically using a Turnigy 9XR mainboard. The old gimbals use 5kOhm sliding potentiometers for trims, which aren't compatible with the 9XR. I need to replace those with microswitches. I've seen some designs that accomplish this, but I'd like to create my own parametric version so I can adjust it as needed.

Here's what I'm looking for:

I need an OpenSCAD design for a trim switch block that can be snapped into the existing gimbal after removing the original potentiometer. This block will hold two microswitches and should fit into the original gimbal space without altering the external packaging of the transmitter. The microswitches I plan to use are 6x6mm types with a 3.4mm button height. I would like to be able to use a different microswitch later.

Here are some key parameters I need to be able to control:

*   **`blx`:** Basic gimbal adapter dimension X, the overall length of the block.
*   **`blh`:** Basic gimbal adapter dimension Y, the height of the main base of the block.
*   **`trimx`:** Trim lever button knob width, the width of the lever that activates the switch.
*   **`knob_height`:** Trim lever button knob height, the thickness of the button on the lever.
*   **`travel`:** Trim button travel restriction block height, how far the lever is allowed to travel.
*   **`snap_height`:** Microswitch fixation snap height, how high the clips for holding the microswitch rise.
*   **`hinge_cutout`:** Cutout radius for integrated lever hinge, this determines how easily the lever rotates (2.2 = hard, 2.6 = soft).
*    **`stegx`**: Length of the trim lever connector bar.
*    **`bspc`**: Distance between microswitch mounts.
*   **`cable_holder`:** A boolean parameter to control if a cable holder hole is included in the design.
*   **`ghost`:** A boolean parameter to control if an example microswitch is shown for design purposes.

The block should have:
*   A main block structure with fixing blocks for the microswitches on each side of the center axis of the main base.
*   Snap-in clips to secure the microswitches.
*   An integrated lever with a button that will press the microswitches.
*   A travel restriction block to limit the lever movement.
*   A connecting bar between the two trim switches.
*   Holes for screws to mount the entire block.
*   Option for cable routing hole.

I'd like it if you could use the BOSL2 library to make sure the code is well-structured and easier to modify later on. Could you also include a module for visualizing the microswitches so I can see how it all fits?  I'd appreciate it if the code is well-commented too.

Thanks a lot!

[Assistant]
my9xr_trimmer.scad:
```
//**************************************************
//*  Trim button block to retrofit into MPX Profi transmitter gimbal
//*  28.11.2014 Henning Stoecklein - free for noncemmercial use
//**************************************************

// Show ghost objects?
ghost = 0 ; // [0:No ghosts, 1:Show additional objects]

// Make cable holder?
cable_holder = 1 ; // [0:No holder, 1:Make cable holder hole]

// Basic gimbal adapter dimension X
blx = 53 ;

// Basic gimbal adapter dimension Y
blh = 5.5;

// Trim lever button knob width
trimx = 6; // [4:8]

// Trim lever button knob height
knob_height = 1.2 ;

// Trim button travel restriction block height
travel = 5.5 ;

// Trim lever height (don't change)
trimy = 8.5;

// Microswitch fixation snap height
snap_height = 0.6 ;

// Cutout radius for integrated lever hinge (2.2 = hard, 2.6 = soft)
hinge_cutout = 2.3;

stegx = 29 ;
bspc  = 6.6 ;

// Trimmerblock
module 9xr_trimmer()
{
	// Basisblock
   difference() {
     union()
     {
		 hull() {
		   translate ([5.5,5.5,0]) cylinder (r=5.5, h=blh, $fn=30) ;
		   translate ([blx-5.5,5.5,0]) cylinder (r=5.5, h=blh, $fn=30) ;
		 }

        // Fixing blocks for Micro switches
        translate ([38-8/2,-4,0]) cube ([8, 6, 8]);
        translate ([15-8/2,-4,0]) cube ([8, 6, 8]);

         // Bar in between
        translate ([(blx-30)/2,0,0]) cube ([30, 2, 8]);

        // Cable holder
        if (cable_holder == 1)
           translate ([blx/2,11,blh]) rotate ([90,0,0]) cylinder (r=2, h=2, $fn=15);
     }

	  // 4-edge-holes and holes for micro switch
     translate ([38-bspc/2,-3.5,0.5]) cube ([bspc, 8, bspc]);
     translate ([15-bspc/2,-3.5,0.5]) cube ([bspc, 8, bspc]);
     translate ([38,4,3.7]) rotate ([90,0,0]) cylinder (r=2, h=10, $fn=20);
     translate ([15,4,3.7]) rotate ([90,0,0]) cylinder (r=2, h=10, $fn=20);

	  // Screw holes
     translate ([(blx-45.2)/2,5.5,-0.1]) cylinder (r=3.3/2, h=6, $fn=20) ;
     translate ([(blx-45.2)/2+45.2,5.5,-0.1]) cylinder (r=3.3/2, h=6, $fn=20);

	  // Chamfers
     translate ([(blx-45.2)/2,5.5,-0.9]) cylinder (r1=3, r2=1, h=2, $fn=20);
     translate ([(blx-45.2)/2+45.2,5.5,-0.9]) cylinder (r1=3, r2=1, h=2, $fn=20);

	  // Big long hole
     hull()
     {
       translate ([blx*0.2,5.5,-0.1]) cylinder (r=3.5, h=10, $fn=20);
       translate ([blx*0.8,5.5,-0.1]) cylinder (r=3.5, h=10, $fn=20);
     }

     // Hole in cable holder if required
     if (cable_holder ==1)
        hull()
        {
	       translate ([blx/2,12,blh]) rotate ([90,0,0]) cylinder (r=0.6, h=4, $fn=15);
	       translate ([blx/2,12,blh-2.5]) rotate ([90,0,0]) cylinder (r=0.6, h=4, $fn=15);
	     }
   }

   // Ramp clips for Snap-in switch fixation
   hull() {
	  translate ([38-2.5/2,0.5,0.5]) cube ([2.5, 0.05, snap_height]);
	  translate ([38-2.5/2,1.95,0.5]) cube ([2.5, 0.05, 0.05]);
   }
   hull() {
	  translate ([15-2.5/2,0.5,0.5]) cube ([2.5, 0.05, snap_height]);
	  translate ([15-2.5/2,1.95,0.5]) cube ([2.5, 0.05, 0.05]);
   }

	// Clips for switch fixation
   translate ([15+2.6,0.55,bspc+0.5]) rotate ([0,45,0]) cube ([1.2, 1.45, 0.5]);
   translate ([15+3.2-bspc,0.55,bspc-0.3]) rotate ([0,-45,0]) #cube ([1.2, 1.45, 0.5]);
   translate ([38+2.6,0.55,bspc+0.5]) rotate ([0,45,0]) #cube ([1.2, 1.45, 0.5]);
   translate ([38+3.2-bspc,0.55,bspc-0.3]) rotate ([0,-45,0]) #cube ([1.2, 1.45, 0.5]);

	// Operation Lever
   translate ([38-5/2,-8.1,0]) cube ([5, 1.4, 5.5]) ;
   translate ([15-5/2,-8.1,0]) cube ([5, 1.4, 5.5]) ;

 	// End block to constrain lever travel
   translate ([38-5/2,-travel,0]) cube ([5, 1.5, 1.5]) ;
   translate ([15-5/2,-travel,0]) cube ([5, 1.5, 1.5]) ;

   // Hole for hinge
   difference()
   {
     union() {
       translate ([(blx-5)/2,-8,0]) cube ([5, 8, 4.6]) ;		// Hinge block

       // Connecting rod between 2 trim switches
       hull() {
			translate ([(blx-stegx)/2,-trimy,0]) cube ([stegx, 1, 4.6]) ;
     		translate ([(blx-stegx)/2,-trimy-3,0.9]) cube ([stegx, 0.5, 3.1]) ;
		 }
     }

     translate ([blx/2-3.2,-7.8,-0.1]) cylinder (r=hinge_cutout, h=10, $fn=30);
     translate ([blx/2+3.2,-7.8,-0.1]) cylinder (r=hinge_cutout, h=10, $fn=30);
   }

   // Trim button (Prism)
   hull() {
     translate ([1+(blx-30)/2,-trimy-3,(blh-3.7)/2]) cube ([trimx, 0.1, 3.1]) ;
     translate ([1+(blx-30)/2,-trimy-7,(blh-1.4)/2]) cube ([trimx, 0.1, knob_height]) ;
   }
   hull() {
     translate ([(blx-30)/2+29-trimx,-trimy-3,(blh-3.7)/2]) cube ([trimx, 1, 3.1]) ;
     translate ([(blx-30)/2+29-trimx,-trimy-7,(blh-1.4)/2]) cube ([trimx, 1, knob_height]) ;
   }
}

module smd_taster()
{
   cube ([5, 5, 1.2], center=true) ;
   translate ([0,0,0.2]) cylinder (r=1, h=1.5, $fn=20, center=true) ;
}

module taster()
{
   cube ([6.2, 6.2, 3.5], center=true) ;
   translate ([0,0,1.6]) cylinder (r=3.4/2, h=6.7, $fn=20, center=true) ;
}

9xr_trimmer() ;

if (ghost == 1)
{
  rotate ([90,0,0]) translate ([(blx-23)/2-0,3.5]) %taster() ;
  rotate ([90,0,0]) translate ([(blx+23)/2+0,3.5]) %taster() ;
}

```


[User]
I'm looking to create a parametric radial bearing in OpenSCAD. I want to be able to control the following:

*   **Overall Dimensions:**
    *   `bearing_diameter`: The outer diameter of the bearing.
    *   `bearing_hole`: The inner diameter (hole) of the bearing.
    *   `bearing_height`: The height of the bearing.
    *   `bearing_thickness`: The thickness of the bearing rings (cup and cone).
*   **Roller Details:**
    *   `sphere_diameter`: The diameter of the individual rollers (spheres).
    *   `number_spheres`: The number of rollers in the bearing.
*   **Cage Configuration:**
    *   `cage_type`: An integer controlling the type of cage:
        *   `0`: No cage.
        *   `1`: Single cage.
        *   `2`: Two half cages.
        *   `3`: Full cage.
*   **Render Options:**
    *   `part_render`: An integer to render specific parts:
        *   `1`: Cup (outer ring).
        *   `2`: Cone (inner ring).
        *   `3`: Cage.
        *   `4`: Roller (individual sphere).
        *   `5`: Set of rollers.
        *   `6`: Full assembled bearing.

I need the code to be well-commented and use a variable `fn` to control the number of facets for smooth circles and spheres. The code should correctly place the rollers between the cup and cone and generate the cage(s) based on the specified `cage_type`. Can you create an OpenSCAD file that can do this, including all of the modules for the cup, cone, rollers, and cages? Please make sure it uses the variable names I've described for the parameters. I do not need to use external libraries.

[Assistant]
Radial_Bearing.scad:
```
/*---------------------------------------------------------\
|     From: Ekobots Innovation Ltda - www.ekobots.com.br   |
|       by: Juan Sirgado y Antico - www.jsya.com.br        |
|----------------------------------------------------------|
|          Program Radial Bearing - 2015/11/29             |
|               All rights reserved 2015                   |
|---------------------------------------------------------*/

/* [ Global ] */

/* [ Bearing (Cup/Cone)] */

// Bearing external diameter in millimeters.
bearing_diameter = 50;
// Bearing internal diameter(central hole) in millimeters.
bearing_hole = 20;
// Bearing height in millimeters.
bearing_height = 15;
// bearing rings thickness in millimeters.
bearing_thickness = 4.5;

/* [ Roller ] */

// sphere diameter;
sphere_diameter = 10;
// number of spheres;
number_spheres = 6;

/* [ Cage ] */

//Type of cage: 0-No Cage; 1-One Cage; 2-Two Half Cages;3-Full Cage;
cage_type = 1; // [0,1,2,3]

/* [ Parts ] */

//Bearing parts to render: 1-Cup; 2-Cone; 3-Cage; 4-Roller; 5-Roller set; 6-Full;
part_render = 6; // [1,2,3,4,5,6]

/* [ Hidden ] */

be = bearing_diameter;  // bearing external diameter
bi = bearing_hole;      // bearing internal diameter
bh = bearing_height;    // bearing height
bt = bearing_thickness; // bearing rings thickness
sd = sphere_diameter;   // sphere diameter;
ns = number_spheres;    // number of spheres;
gr = cage_type;   // type of cage(0-No cage, 1-One cage, 2-Two cages, 3-Full cage)
pr = part_render; // part to render(1-Cup, 2-Cone 3-Cage, 4-Roller, 5-Roller set, 6=Full)
ac = 0.25;  // adjust value for object cut;
ad = sd/10; // adjust value for sphere house cut;
fn = 120;   // number of faces for objects;
//---------------------------------------------------------|
radial_bearing_parts();
//---------------------------------------------------------|
module radial_bearing_parts()
{
   if(pr==1)
     radial_external_ring();
   if(pr==2)
     radial_internal_ring();
   if(pr==3&&gr!=0)
     radial_cage();
   if(pr==4)
     radial_roller();
   if(pr==5)
     radial_rollers();
   if(pr==6)
     radial_bearing();
}
//---------------------------------------------------------|
module radial_bearing()
{
   radial_external_ring();
   radial_internal_ring();
   radial_rollers();
   if((gr==1)||(gr==3))
   {
      radial_cage();
   }
   else if(gr==2)
   {
      for(r=[0,180])
         rotate([r,0,0])
            radial_cage();
   }
}
//---------------------------------------------------------|
module radial_external_ring()
{
   // cup render
   difference()
   {
      translate([0,0,0])
         cylinder(h=bh,d=be,center=true,$fn=fn);
      translate([0,0,0])
         cylinder(h=bh+ac,d=(be-(bt*2)),center=true,$fn=fn);
      translate([0,0,0])
         radial_channel();
   }
}
//---------------------------------------------------------|
module radial_internal_ring()
{
   // cone render
   difference()
   {
      translate([0,0,0])
         cylinder(h=bh,d=bi+(bt*2),center=true,$fn=fn);
      translate([0,0,0])
         cylinder(h=bh+ac,d=bi,center=true,$fn=fn);
      translate([0,0,0])
         radial_channel();
   }
}
//---------------------------------------------------------|
module radial_rollers()
{
   // roller render
   ri = 360/ns;  // rotation incremente;
   for(r=[ri:ri:361])
      rotate([0,0,r])
         translate([(be+bi)/4,0,0])
            radial_roller();
}
//---------------------------------------------------------|
module radial_roller()
{
   // individual roller
   translate([0,0,0])
      sphere(d=sd,center=true,$fn=fn);
}
//---------------------------------------------------------|
module radial_cage()
{
   // cage render
   rd = 360/ns;               // rotation degrees;
   rt = (be-bi)/2-(2*bt)-2;   // ring thickness
   re = (be+bi+sd)/2;         // ring external diamater
   ri = (be+bi-sd)/2;         // ring internal diamater
   cp = gr==2?-sd/2:-sd/1.25; // cut position
   rp = gr==1?cp/4:0;         // ring position
   difference()
   {
      union()
      {
         difference()
         {
            translate([0,0,rp])
               cylinder(h=sd/4,d=re,center=true,$fn=fn);
            translate([0,0,rp])
               cylinder(h=sd/4+ac,d=ri,center=true,$fn=fn);
         }
         intersection()
         {
            difference()
            {
               translate([0,0,0])
                  cylinder(h=bh-1,d=re,center=true,$fn=fn);
               translate([0,0,0])
                  cylinder(h=bh-1+ac,d=ri,center=true,$fn=fn);
            }
            for(r=[rd:rd:361])
               rotate([0,0,r])
                  translate([(be+bi)/4,0,0])
                     rotate([0,90,0])
                        cylinder(h=sd,d=sd*1.3,center=true,$fn=fn);
         }
      }
      if(gr!=3)
         translate([0,0,cp])
            cylinder(h=sd,d=be+ac,center=true,$fn=fn);
      for(r=[rd:rd:361])
         rotate([0,0,r])
            translate([(be+bi)/4,0,0])
               sphere(d=sd+(ad),center=true,$fn=fn);
      for(r=[rd:rd:361])
         rotate([0,0,r+(rd/2)])
            translate([(be+bi)/4,0,0])
                cylinder(h=bh,d=sd/6,center=true,$fn=fn);
   }
}
//---------------------------------------------------------|
module radial_channel()
{
   pi = 3.1415926535897932384626433832795028841971693993751;
   ri = 360/fn;     // rotation incremente;
   ch = (be*pi)/fn; // cylinder height;
   for(r=[ri:ri:361])
      rotate([0,0,r])
         translate([(be+bi)/4,0,0])
            rotate([90,0,0])
               cylinder(h=ch,d=sd+ac,center=true,$fn=fn);
}
//---------------------------------------------------------|
```


[User]
Hey, I'm looking for an OpenSCAD design for a set of universal connectors, like the ones I've seen people use for building frames and structures. I've included some details below to help you understand what I need.

Essentially, I want a single OpenSCAD design or a set of OpenSCAD files that can generate different types of connectors based on parameters. I need to be able to specify:

*   **Outer diameter:** The thickness of the connector's walls.
*   **Inner diameter:** The diameter of the holes that run through the connector, which would typically be used to join sticks/rods.
*   **Connect length:** The length of each connecting "leg" of the connector.
*   **Faces:** A parameter to control the smoothness/number of sides of the curved shapes.

I would like the design to generate the following connector types:

*   **L-connector:** A simple 90 degree corner connector with two connecting legs.
*   **T-connector:** A flat T-shaped connector with three connecting legs.
*   **X-connector:** A flat X-shaped connector with four connecting legs.
*   **LL-connector:** An L-shaped edge connector with three connecting legs - like the L-connector but with a third leg at 90 degrees to the primary edge connection.
*   **TT-connector:** A T-connector with a fourth connecting leg on its side, giving it 4 legs total.
*   **XT-connector:** An X-connector with a fifth connecting leg on its side, giving it 5 legs total.
*   **XX-connector:** A fully 3D cross connector with 6 legs.

The connectors should have a central hole going through each leg where rods can be inserted. For the connectors which do not form a "flat" 2D shape, the holes should still line up so that rods can be attached to the connector to join various structures together. I'm thinking all of the connectors should be built up from cylinders and spheres.

I'd like the OpenSCAD files to be parametric so I can easily customize the dimensions and type of connector I need, and ideally they should be easy to modify if I decide to add additional connector types later. Also, could you make sure all units are in millimeters?

I'm not requesting any specific libraries for this project, and I don't have any particular preferences about how the files are organized, so long as the design is modular and easy to use.

[Assistant]
Universal-connectors-v1.scad:
```
/*
 * Universal connectors generator
 * See connectors type to choose from
 * all units are in milimeters
 *
 * author R. A. - 2015/11/30
 * e-mail: thingiverse@dexter.sk
 * Thingiverse username: dexterko
 *
 * Feel free to modify and distribute, but please keep the credits;-)
 */

outer_diameter = 15;
inner_diameter = 8;
connect_length = 20;
faces = 100; // [6:100]
connector_type = "XX_conn"; // [L_conn:Flat L connector - 2 connects, T_conn:Flat T connector - 3 connects, X_conn:Flat X connector - 4 connects, LL_conn:Edge Connector - 3 connects, TT_conn:T Connector with side connect - 4 connects, XT_conn:X Connector with  side-connect - 5 connects, XX_conn:full 3D Cross Connector - 6 connects]

if (connector_type == "L_conn") {
    L_conn(outer_diameter, inner_diameter, connect_length, faces);
} else if (connector_type == "T_conn") {
    T_conn(outer_diameter, inner_diameter, connect_length, faces);
} else if (connector_type == "X_conn") {
    X_conn(outer_diameter, inner_diameter, connect_length, faces);
} else if (connector_type == "LL_conn") {
    LL_conn(outer_diameter, inner_diameter, connect_length, faces);
} else if (connector_type == "TT_conn") {
    TT_conn(outer_diameter, inner_diameter, connect_length, faces);
} else if (connector_type == "XT_conn") {
    XT_conn(outer_diameter, inner_diameter, connect_length, faces);
} else if (connector_type == "XX_conn") {
    XX_conn(outer_diameter, inner_diameter, connect_length, faces);

}

module L_conn(outer_diameter, inner_diameter, connect_length, faces) {
    difference() {
        union() {
            // Vertical connect
            cylinder(d = outer_diameter, h = connect_length + outer_diameter/2, $fn = faces);

            // Edge connect - solid, no holes
            translate([0, 0, connect_length+outer_diameter/2])
            sphere(d = outer_diameter, $fn = faces);

            // Horizontal connect
            rotate([90, 0, 0])
            translate([0, connect_length+outer_diameter / 2, 0])
            cylinder(d = outer_diameter, h = connect_length + outer_diameter / 2, $fn = faces);
        }

        // Inner hole - vertical
        cylinder(d = inner_diameter , h = connect_length, $fn=faces);

        // Inner hole - horizontal
        rotate([90, 0, 0])
        translate([0, connect_length + outer_diameter / 2, outer_diameter / 2])
        cylinder(d  = inner_diameter, h = connect_length, $fn = faces);
        }
    }

module T_conn(outer_diameter, inner_diameter, connect_length, faces) {
    difference() {
        union() {
            // Vertical connects - upper & lower
            cylinder(d = outer_diameter, h = (connect_length * 2 + outer_diameter), $fn = faces);

            // Horizontal connect - left
            rotate([90, 0, 0])
            translate([0, connect_length + outer_diameter / 2, 0])
            cylinder(d = outer_diameter, h = connect_length + outer_diameter / 2, $fn = faces);
        }

        // Inner hole - vertical
        cylinder(d = inner_diameter , h = (connect_length * 2 + outer_diameter), $fn=faces);

        // Inner hole - horizontal
        rotate([90, 0, 0])
        translate([0, connect_length + outer_diameter / 2, outer_diameter / 2])
        cylinder(d  = inner_diameter, h = connect_length, $fn = faces);
        }
    }

module X_conn(outer_diameter, inner_diameter, connect_length, faces) {
    difference() {
        union() {
            // Vertical connects - upper & lower
            cylinder(d = outer_diameter, h = (connect_length * 2 + outer_diameter), $fn = faces);

            // Horizontal connect - left & right
            rotate([90, 0, 0])
            translate([0, connect_length + outer_diameter / 2, 0 - (connect_length + outer_diameter/2)])
            cylinder(d = outer_diameter, h = (connect_length * 2 + outer_diameter), $fn = faces);
        }

        // Inner hole - vertical
        cylinder(d = inner_diameter , h = (connect_length * 2 + outer_diameter), $fn=faces);

        // Inner hole - horizontal (left + right)
        rotate([90, 0, 0])
        translate([0, connect_length + outer_diameter / 2, outer_diameter / 2])
        cylinder(d  = inner_diameter, h = connect_length, $fn = faces);

        rotate([90, 0, 0])
        translate([0, connect_length + outer_diameter / 2, 0 - (connect_length + outer_diameter/2)])
        cylinder(d  = inner_diameter, h = connect_length, $fn = faces);
        }
    }

module LL_conn(outer_diameter, inner_diameter, connect_length, faces) {
      difference() {
        union() {
            // Vertical connect
            cylinder(d = outer_diameter, h = connect_length + outer_diameter/2, $fn = faces);

            // Edge connect - solid, no holes
            translate([0, 0, connect_length+outer_diameter/2])
            sphere(d = outer_diameter, $fn = faces);

            // Horizontal connect 1
            rotate([90, 0, 0])
            translate([0, connect_length+outer_diameter / 2, 0])
            cylinder(d = outer_diameter, h = connect_length + outer_diameter / 2, $fn = faces);
            // Horizontal connect 2
            rotate([90, 0, 90])
            translate([0, connect_length+outer_diameter / 2, 0])
            cylinder(d = outer_diameter, h = connect_length + outer_diameter / 2, $fn = faces);
        }

        // Inner hole - vertical
        cylinder(d = inner_diameter , h = connect_length, $fn=faces);

        // Inner hole - horizontal 1
        rotate([90, 0, 0])
        translate([0, connect_length + outer_diameter / 2, outer_diameter / 2])
        cylinder(d  = inner_diameter, h = connect_length, $fn = faces);

        // Inner hole - horizontal 2
        rotate([90, 0, 90])
        translate([0, connect_length + outer_diameter / 2, outer_diameter / 2])
        cylinder(d  = inner_diameter, h = connect_length, $fn = faces);
        }
    }

module TT_conn(outer_diameter, inner_diameter, connect_length, faces) {
    difference() {
        union() {
            // Vertical connects - upper & lower
            cylinder(d = outer_diameter, h = (connect_length * 2 + outer_diameter), $fn = faces);

            // Horizontal connect - left
            rotate([90, 0, 0])
            translate([0, connect_length + outer_diameter / 2, 0])
            cylinder(d = outer_diameter, h = connect_length + outer_diameter / 2, $fn = faces);
            // Horizontal connect - front
            rotate([90, 0, 90])
            translate([0, connect_length + outer_diameter / 2, 0])
            cylinder(d = outer_diameter, h = connect_length + outer_diameter / 2, $fn = faces);
        }

        // Inner hole - vertical
        cylinder(d = inner_diameter , h = (connect_length * 2 + outer_diameter), $fn=faces);

        // Inner hole - horizontal left
        rotate([90, 0, 0])
        translate([0, connect_length + outer_diameter / 2, outer_diameter / 2])
        cylinder(d  = inner_diameter, h = connect_length, $fn = faces);
        // Inner hole - horizontal front
        rotate([90, 0, 90])
        translate([0, connect_length + outer_diameter / 2, outer_diameter / 2])
        cylinder(d  = inner_diameter, h = connect_length, $fn = faces);
        }
    }

module XT_conn(outer_diameter, inner_diameter, connect_length, faces) {
    difference() {
        union() {
            // Vertical connects - upper & lower
            cylinder(d = outer_diameter, h = (connect_length * 2 + outer_diameter), $fn = faces);

            // Horizontal connect - left & right
            rotate([90, 0, 0])
            translate([0, connect_length + outer_diameter / 2, 0 - (connect_length + outer_diameter/2)])
            cylinder(d = outer_diameter, h = (connect_length * 2 + outer_diameter), $fn = faces);
            // Horizontal connect - front
            rotate([90, 0, 90])
            translate([0, connect_length + outer_diameter / 2, 0])
            cylinder(d = outer_diameter, h = connect_length + outer_diameter / 2, $fn = faces);
        }

        // Inner hole - vertical - upper & lower
        cylinder(d = inner_diameter , h = (connect_length * 2 + outer_diameter), $fn=faces);

        // Inner hole - horizontal - left & right
        rotate([90, 0, 0])
        translate([0, connect_length + outer_diameter / 2, outer_diameter / 2])
        cylinder(d  = inner_diameter, h = connect_length, $fn = faces);

        rotate([90, 0, 0])
        translate([0, connect_length + outer_diameter / 2, 0 - (connect_length + outer_diameter/2)])
        cylinder(d  = inner_diameter, h = connect_length, $fn = faces);

        // Inner hole - horizontal front
        rotate([90, 0, 90])
        translate([0, connect_length + outer_diameter / 2, outer_diameter / 2])
        cylinder(d  = inner_diameter, h = connect_length, $fn = faces);
        }
    }

 module XX_conn(outer_diameter, inner_diameter, connect_length, faces) {
    difference() {
        union() {
            // Vertical connects - upper & lower
            cylinder(d = outer_diameter, h = (connect_length * 2 + outer_diameter), $fn = faces);

            // Horizontal connect - left & right
            rotate([90, 0, 0])
            translate([0, connect_length + outer_diameter / 2, 0 - (connect_length + outer_diameter/2)])
            cylinder(d = outer_diameter, h = (connect_length * 2 + outer_diameter), $fn = faces);
            // Horizontal connect - front
            rotate([90, 0, 90])
            translate([0, connect_length + outer_diameter / 2, 0])
            cylinder(d = outer_diameter, h = connect_length + outer_diameter / 2, $fn = faces);
            // Horizontal connect - rear
            rotate([90, 0, 90])
            translate([0, connect_length + outer_diameter / 2, 0 - (connect_length + outer_diameter/2)])
            cylinder(d = outer_diameter, h = connect_length + outer_diameter / 2, $fn = faces);
        }

        // Inner hole - vertical - upper & lower
        cylinder(d = inner_diameter , h = (connect_length * 2 + outer_diameter), $fn=faces);

        // Inner hole - horizontal - left & right
        rotate([90, 0, 0])
        translate([0, connect_length + outer_diameter / 2, outer_diameter / 2])
        cylinder(d  = inner_diameter, h = connect_length, $fn = faces);

        rotate([90, 0, 0])
        translate([0, connect_length + outer_diameter / 2, 0 - (connect_length + outer_diameter/2)])
        cylinder(d  = inner_diameter, h = connect_length, $fn = faces);

        // Inner hole - horizontal front
        rotate([90, 0, 90])
        translate([0, connect_length + outer_diameter / 2, outer_diameter / 2])
        cylinder(d  = inner_diameter, h = connect_length, $fn = faces);

        // Inner hole - horizontal rear
        rotate([90, 0, 90])
        translate([0, connect_length + outer_diameter / 2, 0 - (connect_length + outer_diameter/2)])
        cylinder(d  = inner_diameter, h = connect_length, $fn = faces);
        }
    }

```


[User]
I need a parametric OpenSCAD design for a fan gasket and its corresponding mold. The gasket should be customizable based on the fan size, screw hole diameter, screw hole distance, corner radius, gasket height, and airflow diameter. The mold should also be parametric, matching the gasket parameters but also including a wall thickness parameter to define the mold's outer dimensions.

Specifically:

*   I need two modules: one for the fan gasket (`fan_gasket`) and one for its mold (`fan_gasket_mold`).
*   The `fan_gasket` module needs to accept:
    *   `width` (overall fan size, e.g. 30 for a 30x30mm fan)
    *   `screw_diameter` (diameter of the screw holes)
    *   `screw_distance` (distance between the centers of the screw holes)
    *   `corner_radius` (radius of the rounded corners)
    *   `airflow_diameter` (diameter of the central airflow hole)
    *   `height` (height/thickness of the gasket)
*   The `fan_gasket_mold` module should accept the same parameters as `fan_gasket`, plus a `wall_thickness` parameter to define the extra thickness of the mold around the gasket.
*   The gasket should have rounded corners.
*   The screw holes and airflow hole should go all the way through the gasket, with a small overlap to make sure there are no gaps.
*   The mold should be a negative of the gasket, with walls extending beyond the gasket's shape by the specified `wall_thickness`. The base of the mold should also extend below the gasket in the Z direction by the same `wall_thickness`.
*   I need a top-level module called `print_part` that takes a `part` parameter (0 for gasket, 1 for mold) and renders the appropriate part based on this parameter.

I would also like two simpler modules for a quick test; these modules should call the parameterized modules above:
 * `easy_fan_gasket`, taking `width`, `screw_diameter`, and `screw_distance` and using defaults for the other parameters to build a fan gasket.
 * `easy_fan_gasket_mold`, taking `width`, `screw_diameter`, and `screw_distance` and using defaults to build the fan gasket mold for that fan gasket.

Also, could you please provide the code in a single file? I don't need separate files. I don't need any external libraries for this.

[Assistant]
fan_gasket_mold.scad:
```

/////////////////////////////////////////////////////////////////////
//
// File: fan_gasket_mold.scad
// Author: Stephan Mueller
// Date: 2015-12-03
// Description: Customizable fan gasket and suitable mold
//
/////////////////////////////////////////////////////////////////////

// Customizer Settings: //

/* [Options] */

//gasket or gasket mold
part = 0; // [0:fan gasket,1:fan gasket mold]

//fan size, e.g. 30x30 => 30
fan_size = 30; // [10:1:200]

//air_flow_diameter
airflow_diameter = 26; // [6:1:200]

//screw hole diameter
screw_diameter = 3.5; // [1:0.1:10]

//screw distance
screw_distance = 24; // [5:1:200]

//corner radius
corner_radius = 3; // [0:0.1:50]

//gasket height
gasket_height = 2; // [1:0.1:10]

//mold wall thickness
wall_thickness = 3; // [1:0.1:10]

// Static Settings: //

/* [Hidden] */

overlap = 0.04;
$fn = 100;

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

print_part();

module print_part() {
	if (part == 0) {
		fan_gasket(fan_size, screw_diameter, screw_distance, corner_radius, airflow_diameter, gasket_height);
	} else if (part == 1) {
		fan_gasket_mold(fan_size, screw_diameter, screw_distance, corner_radius, airflow_diameter, gasket_height, wall_thickness);
    }
}

module fan_gasket(
    width = 30,                 // gasket size
    screw_diameter = 3.5,      // diameter of the screw holes
    screw_distance = 24,       // distance of the screw hole centers
    corner_radius = 3,         // radius of the corner
    airflow_diameter = 26,    // diameter of the airflow hole
    height = 2                 // gasket height
){
    corner_radius = max(corner_radius, 0.01);

    screw_offset = (width - screw_distance) / 2;

    difference(){
        // main body
        hull(){
            translate([corner_radius, corner_radius, 0])
                cylinder(r = corner_radius, h = height);
            translate([width - corner_radius, corner_radius, 0])
                cylinder(r = corner_radius, h = height);
            translate([corner_radius, width - corner_radius, 0])
                cylinder(r = corner_radius, h = height);
            translate([width - corner_radius, width - corner_radius, 0])
                cylinder(r = corner_radius, h = height);
        }

        // holes for screws and airflow
        union(){
            // air flow hole
            translate([width / 2, width / 2, -overlap])
                cylinder(d = airflow_diameter, h = height + 2 * overlap);

            // screw holes
            translate([screw_offset, screw_offset, -overlap])
                cylinder(d = screw_diameter, h = height + 2 * overlap);
            translate([screw_offset + screw_distance, screw_offset, -overlap])
                cylinder(d = screw_diameter, h = height + 2 * overlap);
            translate([screw_offset, screw_offset + screw_distance, -overlap])
                cylinder(d = screw_diameter, h = height + 2 * overlap);
            translate([screw_offset + screw_distance, screw_offset + screw_distance, -overlap])
                cylinder(d = screw_diameter, h = height + 2 * overlap);
        }
    }
}

module fan_gasket_mold(
    width = 30,                 // gasket size
    screw_diameter = 3.5,      // diameter of the screw holes
    screw_distance = 24,       // distance of the screw hole centers
    corner_radius = 2,         // radius of the corner
    airflow_diameter = 27,    // diameter of the airflow hole
    height = 2,                // gasket height
    wall_thickness = 3        // wall thickness of the mold
){
    difference(){
        // main mold
        cube([width + 2 * wall_thickness, width + 2 * wall_thickness, height + wall_thickness]);

        // subtract fan gasket
        translate([wall_thickness, wall_thickness, wall_thickness])
            fan_gasket(width, screw_diameter, screw_distance, corner_radius, airflow_diameter, height + overlap);
    }

}

module easy_fan_gasket(
    width = 30,                 // gasket size
    screw_diameter = 3.5,      // diameter of the screw holes
    screw_distance = 24       // distance of the screw hole centers
){
    fan_gasket(width, screw_diameter, screw_distance, floor(screw_diameter), width - 4, 2);
}

module easy_fan_gasket_mold(
    width = 30,                 // gasket size
    screw_diameter = 3.5,      // diameter of the screw holes
    screw_distance = 24       // distance of the screw hole centers
){
    fan_gasket_mold(width, screw_diameter, screw_distance, floor(screw_diameter), width - 4, 2, 3);
}

```


[User]
Hey, I'm looking to create a set of universal connectors, but this time I need them to be rectangular, not round. I've seen some examples on Thingiverse, but I'd like to be able to generate them parametrically using OpenSCAD. I want a single file to generate all the different connector types, if possible.

I need a few different connector types:

*   **I-connector:** A basic straight connector with two connecting ends.
*   **L-connector:** A 90-degree connector, also with two connecting ends.
*   **T-connector:** A flat T-shape, with three connecting ends.
*  **X-connector:** A flat cross shape, with four connecting ends.
*   **LL-connector:** An edge connector, a bit like an L-shape with three connecting ends.
*   **TT-connector:** A T-shape with a side connection, making four connecting ends in total.
*   **XT-connector:** Like an X-shape but with an extra side connection, giving five total connection points.
*   **XX-connector:** A full 3D cross connector, with six connection points.

I want to define a few key parameters that will be common across all connector types. These are:
 *   `outer_width`: The thickness of the connector wall, measured in millimeters.
*   `hole_width`: The size of the square holes in the connectors, measured in millimeters.
*   `connect_length`: The length of each connecting "leg", measured in millimeters.

And for the overall connector type, I'd like to have a parameter called `connector_type`, which can take values such as "I_conn", "L_conn", "T_conn", "X_conn", "LL_conn", "TT_conn", "XT_conn", and "XX_conn" to choose which connector is generated. I expect the file to output one connector type at a time.

Can you generate an OpenSCAD file that would allow me to create these connectors based on these parameters? Thanks!

[Assistant]
Universal-connectors-rect-v1.scad:
```
/*
 * Universal connectors generator - rectangular version
 * See connectors type to choose from
 * all units are in milimeters
 *
 * author R. A. - 2015/12/01
 * e-mail: thingiverse@dexter.sk
 * Thingiverse username: dexterko
 *
 * Feel free to modify and distribute, but please keep the credits;-)
 */

outer_width = 12;
hole_width = 8;
connect_length = 20;
connector_type = "XX_conn"; // [I_conn:Bare I connector - 2 connects, L_conn:Flat L connector - 2 connects, T_conn:Flat T connector - 3 connects, X_conn:Flat X connector - 4 connects, LL_conn:Edge Connector - 3 connects, TT_conn:T Connector with side connect - 4 connects, XT_conn:X Connector with  side-connect - 5 connects, XX_conn:full 3D Cross Connector - 6 connects]

if (connector_type == "I_conn") {
    I_conn(outer_width, hole_width, connect_length);
} else if (connector_type == "L_conn") {
    L_conn(outer_width, hole_width, connect_length);
} else if (connector_type == "T_conn") {
    T_conn(outer_width, hole_width, connect_length);
} else if (connector_type == "X_conn") {
    X_conn(outer_width, hole_width, connect_length);
} else if (connector_type == "LL_conn") {
    LL_conn(outer_width, hole_width, connect_length);
} else if (connector_type == "TT_conn") {
    TT_conn(outer_width, hole_width, connect_length);
} else if (connector_type == "XT_conn") {
    XT_conn(outer_width, hole_width, connect_length);
} else if (connector_type == "XX_conn") {
    XX_conn(outer_width, hole_width, connect_length);

}

module I_conn(outer_width, hole_width, connect_length) {
    difference() {
      cube([outer_width, outer_width, connect_length*2]);

      translate([(outer_width-hole_width)/2, (outer_width-hole_width)/2, 0])
      cube([hole_width, hole_width, connect_length*2]);
    }
}

module L_conn(outer_width, hole_width, connect_length) {
    difference() {
        union() {
            // Vertical connect
            translate([0, 0, outer_width])
            cube([outer_width, outer_width, connect_length]);

            // Edge connect - solid, no holes
            cube([outer_width, outer_width, outer_width]);

            // Horizontal connect
            rotate([90, 0, 0])
            translate([0, 0, 0])
            cube([outer_width, outer_width, connect_length]);
        }

        // Inner hole - vertical
        translate([(outer_width-hole_width)/2, (outer_width-hole_width)/2, outer_width])
        cube([hole_width, hole_width, connect_length]);

        // Inner hole - horizontal
        rotate([90, 0, 0])
        translate([(outer_width-hole_width)/2, (outer_width-hole_width)/2, 0])
        cube([hole_width, hole_width, connect_length]);
        }
    }

module T_conn(outer_width, hole_width, connect_length) {
    difference() {
        union() {
            // Vertical connect
            translate([0, 0, outer_width])
            cube([outer_width, outer_width, connect_length]);

            // Edge connect - solid, no holes
            // cube([outer_width, outer_width, outer_width]);

            // Horizontal connect
            rotate([90, 0, 0])
            translate([0, 0, 0-connect_length-outer_width])
            cube([outer_width, outer_width, connect_length*2+outer_width]);
        }

        // Inner hole - vertical
        translate([(outer_width-hole_width)/2, (outer_width-hole_width)/2, outer_width])
        cube([hole_width, hole_width, connect_length]);

        // Inner hole - horizontal
        rotate([90, 0, 0])
        translate([(outer_width-hole_width)/2, (outer_width-hole_width)/2, 0-connect_length-outer_width])
        cube([hole_width, hole_width, connect_length*2+outer_width]);
        }
    }

module X_conn(outer_width, hole_width, connect_length) {
    difference() {
        cube([(connect_length*2)+outer_width, (connect_length*2)+outer_width, outer_width]);

        translate([-1,-1,-1])
        cube([connect_length+1,connect_length+1, outer_width+2]);

        translate([connect_length+outer_width, -1, -1])
        cube([connect_length+1, connect_length+1, outer_width+2]);

        translate([-1, connect_length+outer_width, -1])
        cube([connect_length+1, connect_length+1, outer_width+2]);

        translate([connect_length+outer_width, connect_length+outer_width, -1])
        cube([connect_length+1, connect_length+1, outer_width+2]);

        // Inner hole 1
        translate([connect_length+(outer_width-hole_width)/2, 0, (outer_width-hole_width)/2])
        cube([hole_width, connect_length, hole_width]);

        // Inner hole 2
        translate([connect_length+(outer_width-hole_width)/2, connect_length+outer_width, (outer_width-hole_width)/2])
        cube([hole_width, connect_length, hole_width]);

        // Inner hole 3(see through)
        translate([0, connect_length+((outer_width-hole_width)/2), (outer_width-hole_width)/2])
        cube([connect_length*2+outer_width, hole_width, hole_width]);
        }
    }

module LL_conn(outer_width, hole_width, connect_length) {
    difference() {
        union() {
            cube([connect_length+outer_width, connect_length+outer_width, outer_width]);
            translate([connect_length, connect_length, outer_width])
            cube([outer_width, outer_width, connect_length]);
        }
        translate([-1,-1,-1])
        cube([connect_length+1,connect_length+1, outer_width+2]);

        // Inner hole 1
        translate([connect_length+(outer_width-hole_width)/2, 0, (outer_width-hole_width)/2])
        cube([hole_width, connect_length, hole_width]);

        // Inner hole 2(see through)
        translate([0, connect_length+((outer_width-hole_width)/2), (outer_width-hole_width)/2])
        cube([connect_length, hole_width, hole_width]);

        translate([connect_length+(outer_width-hole_width)/2, connect_length+(outer_width-hole_width)/2, outer_width])
        cube([hole_width, hole_width, connect_length]);
        }
    }

module TT_conn(outer_width, hole_width, connect_length) {
    difference() {
        union() {
            cube([(connect_length*2)+outer_width, connect_length+outer_width, outer_width]);
            translate([connect_length, connect_length, outer_width])
            cube([outer_width, outer_width, connect_length]);
        }
        translate([-1,-1,-1])
        cube([connect_length+1,connect_length+1, outer_width+2]);

        translate([connect_length+outer_width, -1, -1])
        cube([connect_length+1, connect_length+1, outer_width+2]);

        // Inner hole 1
        translate([connect_length+(outer_width-hole_width)/2, 0, (outer_width-hole_width)/2])
        cube([hole_width, connect_length, hole_width]);

        // Inner hole 2(see through)
        translate([0, connect_length+((outer_width-hole_width)/2), (outer_width-hole_width)/2])
        cube([connect_length*2+outer_width, hole_width, hole_width]);

        translate([connect_length+(outer_width-hole_width)/2, connect_length+(outer_width-hole_width)/2, outer_width])
            cube([hole_width, hole_width, connect_length]);
        }
    }

module XT_conn(outer_width, hole_width, connect_length) {
    difference() {
        union() {
            cube([(connect_length*2)+outer_width, (connect_length*2)+outer_width, outer_width]);
            translate([connect_length, connect_length, outer_width])
            cube([outer_width, outer_width, connect_length]);
        }
        translate([-1,-1,-1])
        cube([connect_length+1,connect_length+1, outer_width+2]);

        translate([connect_length+outer_width, -1, -1])
        cube([connect_length+1, connect_length+1, outer_width+2]);

        translate([-1, connect_length+outer_width, -1])
        cube([connect_length+1, connect_length+1, outer_width+2]);

        translate([connect_length+outer_width, connect_length+outer_width, -1])
        cube([connect_length+1, connect_length+1, outer_width+2]);

        // Inner hole 1
        translate([connect_length+(outer_width-hole_width)/2, 0, (outer_width-hole_width)/2])
        cube([hole_width, connect_length, hole_width]);

        // Inner hole 2
        translate([connect_length+(outer_width-hole_width)/2, connect_length+outer_width, (outer_width-hole_width)/2])
        cube([hole_width, connect_length, hole_width]);

        // Inner hole 3(see through)
        translate([0, connect_length+((outer_width-hole_width)/2), (outer_width-hole_width)/2])
        cube([connect_length*2+outer_width, hole_width, hole_width]);

        translate([connect_length+(outer_width-hole_width)/2, connect_length+(outer_width-hole_width)/2, outer_width])
            cube([hole_width, hole_width, connect_length]);
        }
    }

module XX_conn(outer_width, hole_width, connect_length) {
    difference() {
        union() {
            translate([0, 0, connect_length])
            cube([(connect_length*2)+outer_width, (connect_length*2)+outer_width, outer_width]);

            translate([connect_length, connect_length, connect_length+outer_width])
            cube([outer_width, outer_width, connect_length]);

            translate([connect_length, connect_length, 0])
            cube([outer_width, outer_width, connect_length]);
        }
        translate([-1, -1, connect_length-1])
        cube([connect_length+1,connect_length+1, outer_width+2]);

        translate([connect_length+outer_width, -1, connect_length-1])
        cube([connect_length+1, connect_length+1, outer_width+2]);

        translate([-1, connect_length+outer_width, connect_length-1])
        cube([connect_length+1, connect_length+1, outer_width+2]);

        translate([connect_length+outer_width, connect_length+outer_width, connect_length-1])
        cube([connect_length+1, connect_length+1, outer_width+2]);

        // Inner hole 1
        translate([connect_length+(outer_width-hole_width)/2, 0, (outer_width-hole_width)/2+connect_length])
        cube([hole_width, connect_length, hole_width]);

        // Inner hole 2
        translate([connect_length+(outer_width-hole_width)/2, connect_length+outer_width, (outer_width-hole_width)/2+connect_length])
        cube([hole_width, connect_length, hole_width]);

        // Inner hole 3(see through)
        translate([0, connect_length+((outer_width-hole_width)/2), (outer_width-hole_width)/2+connect_length])
        cube([connect_length*2+outer_width, hole_width, hole_width]);

        // Inner hole 4
        translate([connect_length+(outer_width-hole_width)/2, connect_length+(outer_width-hole_width)/2, connect_length+outer_width])
        cube([hole_width, hole_width, connect_length]);

        // Inner hole 5
        translate([connect_length+(outer_width-hole_width)/2, connect_length+(outer_width-hole_width)/2, 0])
        cube([hole_width, hole_width, connect_length]);
        }
    }

```