[User]
Hey, I'm looking to get some help designing a pair of customizable sunglasses in OpenSCAD. I'd like them to have a kind of futuristic, almost "Back to the Future" vibe, but also be practical enough for light use.

Here's what I'm envisioning:

*   **Main Lens Frame:** The main part of the glasses should be a cylindrical shape with a flattened front, like a slightly squished tube. I want to be able to control the overall diameter of this lens frame. I'm thinking a parameter like `glasses_size` that sets the distance between the ears, probably ranging from 100mm to 200mm. I also need a parameter for the overall thickness of the frame called `glasses_thick` ranging from 1-5mm.
*   **Hole Pattern:** Instead of a solid lens, I want some kind of pattern for ventilation and style. This should be configurable. I’d like a parameter called `hole_type` with three options: 0 for no holes (although this is probably not that useful), 1 for a grid of small cylindrical holes, and 2 for a grid of thin strips. And then, for either of those hole patterns, I need a `holes_distance` parameter which controls how far apart the holes or strips are, maybe a range of 2mm to 5mm or so, in both the X and Z axis.
*   **Arms:** The arms should attach to the main lens frame at the sides, with a slight angle outward. They should be relatively thin with a rounded shape at the ends that rest on your ears. I'd like the arms to also have the thickness parameter of `glasses_thick`.
*   **Rounded Corners:** I want to make sure all the corners are nicely rounded, especially where the arms attach and on the cube shapes. I want the rounding on each part to be configurable within each module.

I want a single OpenSCAD file that generates these glasses, so I'll need modules for the main frame, the arms, and the hole pattern. I don't want any hardcoded dimensions except in the ranges of the parameters. Please use a reasonable amount of faces for the rounded parts, maybe about 120, but don’t add that to a parameter.

I’m trying to build this from scratch so please don't use any existing libraries. Thanks!

[Assistant]
Glasses.scad:
```
/*---------------------------------------------------------\
|     From: Ekobots Innovation Ltda - www.ekobots.com      |
|       by: Juan Sirgado y Antico - www.jsya.com.br        |
|----------------------------------------------------------|
|             Program Galsses - 2014/10/15                 |
|               All rights reserved 2015                   |
|---------------------------------------------------------*/

/* [ Global ] */

// Which is the size for your glasses? It is the distance between ears in millimeters.
glasses_size = 160; // [100:10:200]

// Which is the thick for your glasses? It is the thick of the lens and arms in millimeters.
glasses_thick = 2;  // [1,2,3,4,5]

// Whitch type of hole you want? The values are: 0=no hole, 1=holes or 2=strips.
hole_type = 1;  // [0,1,2]

// Witch distance between holes or strips you want? It is the distance for x and z axes in millimeters.
holes_distance = 5;  // [2:0.5:5]

/* [ Hidden ] */
d=glasses_size;      // glasses diameter;
h=50;                // glasses height;
t=glasses_thick;     // glasses thick;
a=0.2;               // object cut adjust value;
f=120;               // number of faces in object;
ht = hole_type;      // type of holes  ;
hd = holes_distance; // distance between holes;
//---------------------------------------------------------|
// preview[view:south west, tilt:bottom diagonal]
//---------------------------------------------------------|
glasses();
//---------------------------------------------------------|
module glasses()
{
   difference()
   {
      union()
      {
         translate([0,0,0])
            glasses_len();
         for(x=[(d-t)/2,-(d-t)/2])
            translate([x+(x<0?6:-6),28,0])
               rotate([0,0,x>0?10:-10])
                  glasses_arm();
      }
      for(x=[40,-40])
         translate([x,(-d/2)+20,0])
            rotate([90,0,0])
               glasses_holes();
   }
}
//---------------------------------------------------------|
module glasses_len()
{
   difference()
   {
      translate([0,0,0])
         cylinder(h=h,d=d,center=true,$fn=f);
      translate([0,0,0])
         cylinder(h=h+a,d=d-(t*2),center=true,$fn=f);
      translate([0,(d/4),0])
         cube([d+a,(d/2)+10,h+a],center=true);
      translate([0,0,33])
         rotate([-20,0,0])
            cylinder(h=h,d=d+a,center=true,$fn=f);
      translate([0,(-d/2)+t,25])
          scale([20,80,50])
            sphere(d=1,center=true,$fn=f);
      for(x=[13.5,-13.5])
      {
         difference()
         {
            translate([x+(x<0?5:-5),(-d/2)+2.5,20])
               cube([20,30,10.2],center=true);
            translate([x+(x>0?5:-5),(-d/2)+2.5,15])
               rotate([90,0,0])
                  cylinder(h=30+a,d=20,center=true,$fn=f);
         }
      }
   }
}
//---------------------------------------------------------|
module glasses_arm()
{
   difference()
   {
      union()
      {
         translate([0,0,-7.5])
            cube([t,68,h-15],center=true);
         translate([0,35,(h/2)-35])
            cube_rounded([t,20,h-20],r=5,a=0);
      }
      translate([0,-2,(h/2)-12.25])
         rotate([-20,0,0])
            cube_rounded([t+a,80,h-20],r=10,a=0);
   }
}
//---------------------------------------------------------|
module glasses_holes()
{
   if(ht==0)
   {
      // do noting, no holes.
   }
   else if(ht==1)
   {
      for(x=[-hd*5:hd:hd*5])
         for(y=[-hd*4:hd:hd*4])
            translate([x,y,0])
               cylinder(h=50,d=1,center=true,$fn=f);
   }
   else if(ht==2)
   {
      for(x=[-hd*5:hd:hd*5])
         translate([x,y,0])
            cube([1,h-10,40],center=true);
   }
}
//---------------------------------------------------------|
module cube_rounded(xyz=[20,10,5],r=1,a=2)
{
   // cut corners in x -> a=0 or y -> a=1 or z -> a=2
   x = xyz[0]; // x axis length
   y = xyz[1]; // y axis length
   z = xyz[2]; // z axis length
   ra=a==0?[0,90,0]:
      a==1?[90,0,0]:
           [0,0,0];
   difference()
   {
      // main cube no translation and no rotation
      translate([0,0,0])
         rotate([0,0,0])
            cube(xyz,center=true);
      // corner cut rotation, default cut is z
      rotate(ra)
         cube_corners(x=x,y=y,z=z,r=r,a=a);
   }
}
//---------------------------------------------------------|
module cube_corners(x=20,y=10,z=5,r=1,a=2)
{
   c = 0.2;    // correction
   // points and rotation for z corners
   px = [[-z,-y,0,-1,-1,0,0],[z,-y,0,1,-1,0,90],
        [z,y,0,1,1,0,180],[-z,y,0,-1,1,0,270]];
   py = [[-x,-z,0,-1,-1,0,0],[x,-z,0,1,-1,0,90],
        [x,z,0,1,1,0,180],[-x,z,0,-1,1,0,270]];
   pz = [[-x,-y,0,-1,-1,0,0],[x,-y,0,1,-1,0,90],
        [x,y,0,1,1,0,180],[-x,y,0,-1,1,0,270]];
   p=a==0?px:a==1?py:pz;
   d=a==0?x:a==1?y:z;
   for(i=p)
   {
      translate([(i[0]-r*i[3])/2,
                 (i[1]-r*i[4])/2,
                 (i[2]-r*i[5])/2])
         rotate([0,0,i[6]])
            cube_border(z=d,r=r,c=c);
   }
}
//---------------------------------------------------------|
module cube_border(z=10,r=1,c=2)
{
   // cube border cut
   difference()
   {
      translate([0,0,0])
         cube([r+c,r+c,z+c],center=true);
      translate([r/2,r/2,0])
         cylinder(h=z+(c*2),r=r,center=true,$fn=60);
   }
}
//---------------------------------------------------------|

```


[User]
I need a finger brace designed in OpenSCAD, similar to the one described in this blog post: [https://regillmore.wordpress.com/2015/10/16/3d-printed-finger-brace/](https://regillmore.wordpress.com/2015/10/16/3d-printed-finger-brace/). I’m double-jointed, and my fingers bend the wrong way when I use a mouse for too long. This brace prevents that.

I need it to be parametric, so I can easily adjust it for different finger sizes. Basically, it has two rings – one that sits around the proximal phalanx (the first finger bone) and one around the middle phalanx (the second finger bone). The rings are connected by a short cylinder. The proximal ring should be flat, while the middle ring should be angled slightly. I need to be able to control the diameter of both rings, the thickness of the rings, the width of the ring profile, the angle of the middle ring, and the length of the connecting cylinder.

The rings are essentially a circle that is rotated around the z-axis and then scaled in the y-axis to make the ring wider. They are not just extruded circles. The connecting cylinder is also rotated to be vertical. The whole brace needs to be translated such that the rings start at z=0. The brace should be centered on the x-axis, with its connecting cylinder offset in the y direction.

Could you generate the OpenSCAD code for this? I want to make sure that the variables for each dimension are clearly named and easy to find in the code. I also want to have a variable for the resolution `$fn`.

I'd prefer it if the design was created with minimal external library dependencies, but if you need to use a library, I would prefer BOSL2.

[Assistant]
rings.scad:
```
Dproximal = 22;
Dmiddle = 19;
ring_thickness = 3;
width_ratio = 2;
ring_angle = 60;
$fn = 50;

translate([0,0,(ring_thickness*width_ratio)/2]) {
    // proximal ring, lays flat
    translate([(Dproximal + ring_thickness)/2,0,0]) {
        rotate_extrude() {
            translate([(Dproximal + ring_thickness)/2,0,0]) {
                scale([1,width_ratio,1]) {
                    circle(d=ring_thickness);
                };
            };
        };
    };

    // middle ring, at angle
    rotate([0,-ring_angle,0]) {
        translate([(Dmiddle + ring_thickness)/2,0,0]) {
            rotate_extrude() {
                translate([(Dmiddle + ring_thickness)/2,0,0]) {
                    scale([1,width_ratio,1]) {
                        circle(d=ring_thickness);
                    };
                };
            };
        };
    };

    //joining cylinder
    translate([0,(Dproximal + Dmiddle)/6,0]) {
        rotate([90,0,0]) {
            cylinder(h=(Dproximal + Dmiddle)/3, d=ring_thickness*width_ratio);
        };
    };
};
```


[User]
Okay, I need a parametric OpenSCAD design for a laundry rack repair clamp. It's meant to fix broken wires on a typical metal laundry rack. I've got some basic ideas based on an existing design, and I'll explain the key features and parameters I'd like to control.

The basic idea is a two-part clamp. One part is a tube that wraps around the frame of the laundry rack, and the other part is a clamp that secures the broken wire. These two parts need to be connected rigidly and have the ability to be fastened together.

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

*   **`lrDiaFrame`**: The diameter of the laundry rack's outer frame (where the wires attach). I need to be able to add a bit extra to this so the clamp fits tightly.
*   **`lrDiaWire`**: The diameter of the individual wires of the rack. Again, I'll probably need to add a little bit here to make sure the wire is held securely.
*   **`clFrameLen`**: The length of the tube that goes around the frame.
*   **`clFrameAsymmetric`**: A boolean (0 or 1) to make the frame clamp asymmetric. This will shift its position along the tube.
*   **`clCutoutRest`**: The amount of the cutout at the bottom of the frame tube; a smaller diameter cutout will result in a larger lip.
*  **`clCutoutAngle`**: The angle of the cutout.
*   **`clCutoutChamferOffsZ`**: A vertical offset for the chamfer on the cutout edges.
*   **`wcLen`**: The length of the wire clamp portion.
*   **`wcDia`**: The thickness of the wire clamp's tube. This should be something that I can adjust to ensure I get a good fit to the wires while also leaving enough material for strength.
*   **`wcBlockHeight`**: The height of the block that contains the nuts.
*   **`wcOffsetY`**: The offset of the wire clamp relative to the center of the frame tube. This will allow me to make the hole for the wire cut deeper into the main tube, or shallow.
*   **`wcOffsetZshape`**: An optical tuning offset for shaping the "cantilever" part of the wire clamp
*   **`nutDia`**: The diameter of the nut to be used, essentially the wrench size.
*   **`nutSlotHeight`**: The height of the slot for the nut.
*  **`nutPosListY`**: A list of Y positions for where the nuts are positioned along the wire clamp.
*   **`scrDia`**: The diameter of the screw.
*   **`scrDiaHead`**: The diameter of the screw's head.
*   **`scrOffsZ`**: An offset in Z for the screw, to ensure the screw head sits on the material rather than the nut.

I'd also like to have some different modes for rendering this.
* MODE 0: Prints with an optimal orientation, which will be rotated 90 degrees along the Y axis and translated to a particular point.
* MODE 1: Shows the part alone.
* MODE 2: Shows the part with the frame and wire rendered in place.
* MODE 3: Shows the raw clamp, along with the frame and wire, as well as the cutouts.
* MODE 4: Shows only the nut slot geometry, and doesn't render the part.

The design should also be reasonably printable, using standard FDM printers. I think it can be accomplished with standard OpenSCAD libraries. I do not want to use any external libraries. Thanks!

[Assistant]
LaundryRackRepairKit_V11.scad:
```
//
// LAUNDRY RACK REPAIR KIT, V1.1
// FMMT666(ASkr) 10/2015
//

//
// Fix a wire - save a rack.
//
//

//
// - All units in [mm].
//
// - Intentionally no "Thingiverse Customizer" variable descriptions in here.
//   These would only clutter the source...
//
// - Usually (TM), you only need to modify the two parameters
//     * lrDiaFrame, the diameter of the outer frame, to where the "wires" are
//                   attached to and
//     * lrDiaWire,  the diameter of the wires.
//
// - Fairly big wire diameters might lead to a hole in the frame clamp's back.
//   In that case, you can either increase 'wcDia' or reduce 'wcOffsetY'.
//   The latter will determine the depth of the hole for the wire in the
//   frame clamp. Use MODE 3 to watch that effect.
//
// - The rest shouldn't be that hard to understand.
//   Good luck :-)

// ===============================================================================
// laundry rack parameters (used to cut the holes)
//
lrDiaFrame =            14.7;  // diameter of the rack's frame, add ~0.5mm
lrDiaWire =              3.3;  // diameter of the wires, add ~0.7mm

/* [HIDDEN] */

// ===============================================================================
// wire clamp parameters
//
clFrameLen =            13.0;  // length of the tube around the frame
clFrameAsymmetric =        1;  // 0/1; if 1 (def.) the frame clamp will be asymmetric
clCutoutRest =           1.0;  // cutout bottom, but with a slightly smaller diameter
clCutoutAngle =         15.0;  // angle of the cutout
clCutoutChamferOffsZ =   2.0;  // chamfered cutout edges; set by trial and error ;-)
wcLen =                 40.0;  // length of the tube around the wire
wcDia =                  7.8;  // thickness of the wire tube
wcBlockHeight =         10.0;  // height of the block with the nuts
wcOffsetY =    -lrDiaFrame/3;  // y offset of the wire (cut the hole a little deeper)
wcOffsetZshape =         3.0;  // optical tuning to match the shape of the "cantilever"

// ===============================================================================
// nut/screw parameters
//
nutDia =                 6.0;  // nut diameter, wrench size
nutSlotHeight =          3.2;  // height of the nut's slot
nutPosListY =      [ 20,35 ];  // y positions of where to place nuts
scrDia =                 3.8;  // diameter of screw
scrDiaHead =             6.0;  // diameter of screw head
scrOffsZ =               3.0;  // additional space between screw head and nut

//
// CHOOSE MODE HERE
//
//   0 = PART IN PRINTING POSITION
//   1 = PART
//   2 = PART WITH FRAME AND WIRE
//   3 = EDIT
//   4 = EDIT, NUT SLOT
//
MODE = 0;

// ===============================================================================
// ===============================================================================
// ===============================================================================
// NO CHANGES BELOW HERE (HOPEFULLY =)
CP = 150;                               // "CYLINDER PRECISION" ($fn parameter)
ZPOSWIRE = lrDiaFrame/2 + lrDiaWire/2;  // z position of the wire
LGREEN = [0.8,1,0.7];
// Reminder:
// Minimum diameter of wcDia, for no holes on the opposing side of the nut slots:
//   wcDiaMin = 2 * ( layerHeight + 3.47mm ) | for a std. 3mm nut (6mm)
// universal:
//   wcDiaMin = 2 * ( n*layerHeight + 1.155 * ( nutDia / 2 ) )

// ===============================================================================

if( MODE == 0 )
{
  if( clFrameAsymmetric == 1 )
  {
    rotate([0,-90,0])
    translate([wcDia/2,0,0])
    MakePart();
  }
  else
  {
    // emergency printing position (requires support structures)
    rotate([0,-90,0])
    translate([clFrameLen/2,0,0])
    MakePart();
  }
}
else if( MODE == 1 )
{
  MakePart();
}
else if( MODE == 2 )
{
  MakePart();
  FrameAndWire();
}
else if( MODE == 3 )
{
  ChamferCutout();
  Cutout();
  FrameAndWire();
  CutSlotsAndHoles();
  color( LGREEN, 0.5 )
  CompleteClampRaw();
}
else if( MODE == 4 )
{
  NutSlot( nutDia, nutSlotHeight, 20 );
}

// ===============================================================================
// ===
module MakePart()
{
  difference()
  {
    // the raw clamp
    color( LGREEN, 1.0 )
    CompleteClampRaw();

    // cut the frame and wire holes
    FrameAndWire();
    // cut the slots and vertical holes
    CutSlotsAndHoles();

    // cut the cutout and chamfer it
    Cutout();
    ChamferCutout();
  }
}

// ===============================================================================
// ===
module ChamferCutout()
{
  // chamfer the cutout edges
  rotate( [clCutoutAngle, 0, 0] )
  translate( [ 0, 0, -1.5 * ZPOSWIRE + clCutoutChamferOffsZ ] )
  rotate( [ 45,0,0 ] )
  cube([ 2*clFrameLen + 2, lrDiaFrame - clCutoutRest, lrDiaFrame - clCutoutRest ],
    center = true);
}

// ===============================================================================
// ===
module Cutout()
{
  // cutout
  rotate( [clCutoutAngle, 0, 0] )
  translate( [ 0, 0, -1.5 * ZPOSWIRE ] )
  cube([ 2*clFrameLen, lrDiaFrame - clCutoutRest, 3*ZPOSWIRE ], center = true);
}

// ===============================================================================
// ===
module FrameAndWire()
{
  // the rack and wire
  color([0.2,0.2,0.2])
  LaundryRack();
}

// ===============================================================================
// ===
module CutSlotsAndHoles()
{
  // nut slots and holes
  for( y = nutPosListY )
  {
    // the slots, incl. the screw head holes (bottom)
    translate( [ 0, y, -nutSlotHeight + ZPOSWIRE - wcDia/2 ] )
    NutSlot( nutDia, nutSlotHeight, 20 );

    // the holes for the screw (top)
    translate( [ 0, y, -2*ZPOSWIRE ] )
    cylinder( r = scrDia/2, h = 3*ZPOSWIRE, $fn = CP );
  }
}

// ===============================================================================
// ===
module CompleteClampRaw()
{
  union()
  {
    // the big tube for the frame
    //color( LGREEN, 0.5 )
    FrameTube();

    // the "cantilever" clamp for the wire
    //color( LGREEN, 0.5 )
    WireClampNew();
  }
}

// ===============================================================================
// ===
module WireClampNew()
{
  hull()
  {
    // far y, top
    translate( [0, wcLen, ZPOSWIRE] )
    sphere( r = wcDia/2, $fn = CP );
    // far y, bot
    translate( [0, wcLen, ZPOSWIRE - wcBlockHeight] )
    sphere( r = wcDia/2, $fn = CP );
    // center, top
    translate( [0, 0, ZPOSWIRE] )
    sphere( r = wcDia/2, $fn = CP );
    // center, bot
    translate( [0, 0, -ZPOSWIRE + wcOffsetZshape ] )
    sphere( r = wcDia/2, $fn = CP );
  }//END hull
}

// ===============================================================================
// ===
module WireClamp()
{

  // qubic part on bottom
  translate( [ -wcDia/2, 0, ZPOSWIRE - wcBlockHeight ] )
  cube( [wcDia, wcLen, wcBlockHeight ] );
  // round part on top
  translate( [0, 0, ZPOSWIRE ] )
  rotate( [-90, 0, 0] )
  cylinder( r = wcDia/2, h = wcLen, $fn = CP );
}

// ===============================================================================
// ===
module FrameTube()
{
  if( clFrameAsymmetric == 1 )
  {
    translate([ clFrameLen/2 - wcDia/2, 0, 0 ])
    rotate( [0, 90, 0] )
    cylinder( r = ZPOSWIRE + wcDia/2, h = clFrameLen, center = true, $fn = CP );
  }
  else
  {
    rotate( [0, 90, 0] )
    cylinder( r = ZPOSWIRE + wcDia/2, h = clFrameLen, center = true, $fn = CP );
  }

}

// ===============================================================================
// ===
module FrameTubeHole()
{
  rotate( [0, 90, 0] )
  cylinder( r = lrDiaFrame/2, h = clFrameLen + 2, center = true, $fn = CP );
}

// ===============================================================================
// ===
module NutSlot( wrenchSize, height, length )
{
  // Saves a little space, because it enteres the material
  // with a flat side.

  union()
  {
    // sink hole for the screw's head
    translate([0,0,-4*ZPOSWIRE - scrOffsZ])
    cylinder( r = scrDiaHead/2, h = 4*ZPOSWIRE+0.1, $fn = CP );

    hull()
    {
      translate([ length, 0, 0])
      rotate([0,0,0])
      NutCut( wrenchSize, height );

      rotate([0,0,0])
      NutCut( wrenchSize, height );
    }//END hull
  }//END union
}

// ===============================================================================
// ===
module NutCut( wrenchSize, height )
{
  cylinder( r = 0.5 * wrenchSize * 1.155, h = height, $fn = 6 );
}

// ===============================================================================
// ===
module LaundryRack()
{
  // wire
  translate( [0, wcOffsetY, lrDiaFrame/2 + lrDiaWire/2 ] )
  rotate( [-90, 0, 0] )
  cylinder( r = lrDiaWire/2, h = 100, $fn = CP );

  // frame
  rotate( [0, 90, 0] )
  cylinder( r = lrDiaFrame/2, h = 100, center = true, $fn = CP );
}

```


[User]
I'm looking to create a customizable spool for storing wires and threads, and I want it to be parametric so I can easily adjust the dimensions. I've seen some designs online but I'd like to have a version with a few specific features.

The spool should have two main parts: a top and a bottom, which can either be rendered separately or together. Both will have an outer guard (or flange), a central cylinder for the winding area, and then cutouts on the flange and slots on both the outer edges and the center for fastening wire ends.

Here are the parameters I'd like to control:

*   `part`: A string parameter to select which part to render, with options "top", "bottom", and "both".
*   `big_diameter`: The diameter of the outer guard (the flange), adjustable from 40 to 160.
*   `flange_thick`: The thickness of the flange and spool walls, from 1 to 4.
*   `cylinder_diameter`: The diameter of the central cylinder, from 10 to 40.
*   `winding_thick`: The width of the winding area, from 5 to 50.
*   `gaps_width`: The width of the slots and holes used to fasten the wire, from 0 to 3.
*   `cut_diameter`: The diameter of the circular cutouts on the outer guard, from 0 to 9.

For the top part, I want:
* An outer flange.
* A central cylinder that goes all the way to the top, it's where the wire will be wound
* Circular cutouts on the flange itself. Six of them, equally spaced.
* Three equally spaced slots on the outside edge of the outer flange for fastening the wire ends.
* A single circular hole with a slot on the center cylinder for fastening.
* A rectangular slot on the cylinder for locking.

For the bottom part, I want:
* An outer flange.
* A slightly smaller central cylinder that doesn't quite reach the top for the winding area.
* Circular cutouts on the flange itself. Six of them, equally spaced.
* Three slots on the outer edge of the outer flange for fastening the wire ends.
* A circular hole with slot on the center cylinder.
* Rectangular locking tabs.
* I want the bottom cylinder's radius to be smaller than the top by a small amount that I would define as `Clearance` which is 0.2.

I'd like to use `$fa = 5; $fs = 0.75;` for the circle quality. I also need a `Clearance` variable set to 0.2. Please make sure that the bottom part has an inner radius that takes `Clearance` into account, and uses that same clearance for the locking tabs as well. I want the locking tabs to fit into the slot on the top part and hold the pieces together.

Could you please generate the OpenSCAD code for this? I'd prefer it to be in a single file.

[Assistant]
WireSpool.scad:
```
/*
Author: Avp (Alexander Purikov)
Design is based on Ben Wittbrodt one: http://www.thingiverse.com/thing:435802
*/

/*[Customizer Variables]*/

//Which part would you like to render?
part			=	"both"; //[top:Top, bottom:Bottom, both:Both]
//Diameter of the outer guard for the spooler
big_diameter	=	50;	//[40:160]
//Thickness of the flange and spool walls
flange_thick	=	1;	//[1:4]
//Diameter of the middle spool cylinder
cylinder_diameter	=	20;	//[10:40]
//Width of the winding area (where the wire will be)
winding_thick	=	10;	//[5:50]
//Width of the slots and holes for fastening wire ends
gaps_width		=	1; //[0:3]
//Diameter of the circle cutouts on outer guard
cut_diameter	=	0;	//[0:9]

/*[hidden]*/
$fa=5; $fs=0.75;
Clearance = 0.2;

big_radius = big_diameter/2;
small_radius = (cylinder_diameter-flange_thick*2)/2;
cut_radius = cut_diameter/2;

output();

module output()
{
	if (part == "top") {
		top();
	} else if (part == "bottom") {
		bottom();
	} else if (part == "both") {
		top();
		translate([big_radius*2+5,0,0])
		bottom();
	}
}

module top()
{
	difference()
	{
		union()
		{
			cylinder(r=big_radius, h=flange_thick); //Outer flange

			cylinder(r=small_radius+flange_thick, h=flange_thick+winding_thick);	//Inner cylinder
		}

		for (i=[1:6])
		{
			rotate([0,0,60*i])
			translate([big_radius/2+cut_radius,0,-.1])
				cylinder(r=cut_radius,h=flange_thick+.2); //Flange cutouts
		}
		for (i=[1:3])
		{
			rotate([0,0,120*i+30])
				translate ([big_radius,0,0])
					cube ([big_radius/2,gaps_width,flange_thick*2+0.2], center=true);
		}

		if ( gaps_width > 0 )
		{
			rotate([0,0,30])
					translate ([small_radius+2/2+flange_thick,0,-0.1])
						cylinder ( r=(gaps_width<2) ? 1 : gaps_width/2, h=flange_thick+0.2 );

			translate([0,0,-.15])
				cylinder(r=small_radius, h=winding_thick+flange_thick*2+0.2);	//inner radius cutout
		}
		translate([-small_radius-flange_thick,-1.7,flange_thick*1+0.2])
			cube([small_radius*2+(2*flange_thick)+Clearance,3.2,winding_thick]);		//locking slot
	}
}

module bottom()
{
	difference()
	{
		union()
		{
			cylinder(r=big_radius, h=flange_thick);	//Outer flange
			cylinder(r=small_radius-Clearance, h=flange_thick+winding_thick);	//Inner cylinder

			translate([-small_radius-flange_thick,-1.5,flange_thick*2])
				cube([small_radius*2+(2*flange_thick),3,winding_thick-(flange_thick*2)]);  //locking tabs
		}

		for (i=[1:6])
		{
			rotate([0,0,60*i])
			translate([big_radius/2+cut_radius,0,-.1])
				cylinder(r=cut_radius,h=flange_thick+.2); //Flange cutouts
		}

		if ( gaps_width > 0 )
		{
			for (i=[1:3])
			{
				rotate([0,0,120*i+30])
					translate ([big_radius,0,0])
						cube ([big_radius/2,gaps_width,flange_thick*2+0.2], center=true);
			}

			rotate([0,0,30])
					translate ([small_radius+2/2+flange_thick,0,-0.1])
						cylinder ( r=(gaps_width<2) ? 1 : gaps_width/2, h=flange_thick+0.2 );
			}
		translate([0,0,-.15])
		cylinder(r=small_radius-flange_thick, h=winding_thick+flange_thick*2+0.2); //Inner cylinder cutout
	}
}
```


[User]
Hey, I'm looking to design a clutch alignment tool for a Belarus 1523.4 tractor, and I'm hoping you can help me generate the OpenSCAD files.  It's a bit complex, involving splines, a pilot, and potentially a handle.

Here's the breakdown of what I need, with the dimensions that are specific to the 1523.4:

*   **Spline 1 (Bottom):**
    *   Major diameter: 35mm
    *   Minor diameter: 27.5mm
    *   Number of splines: 12
    *   Length: 80mm

*   **Spline 2 (Top):**
    *   Major diameter: 48mm
    *   Minor diameter: 41.5mm
    *   Number of splines: 16
    *   Length: 60mm

*   **Pilot:**
    *   Diameter: 25mm (this is the bearing ID)
    *   Total Length: 15mm
    *   Guide length: This will be a *percentage* of the total pilot length, say 20% of the 15mm, creating a chamfered portion, so the cylindrical part will be 80% of the length and the chamfered section will be 20%.

*   **Handle:**
    *  This can just be a cylinder on the spline2 side and is not critical in the design.  Start with length of 0mm, and we can adjust it as needed.

I want the tool to be assembled in this order, from the handle side to the pilot side: Handle -> Top Spline -> Bottom Spline -> Pilot. The total length of the splines that engage with the tractor's clutch assembly (the sum of spline1 and spline 2 lengths) should be 140mm.

It is important that the spline lengths are parametric so I can adjust them if needed to fit.  I want this to be easily modifiable if I need to tweak lengths or diameters later.

The splines should use a standard involute profile, if that's possible in OpenSCAD, for the "teeth". Also, I think it would be good if the design included a way to export a single body file, so there isn't any need to handle separate parts (unless there is good reason to do so).

I'd appreciate it if you could generate the OpenSCAD code for this, and perhaps make a note about using a library to generate splines? I don't know of any at the moment.

[Assistant]
belarus_1523.4.scad:
```
// This one better be as fit as possible
spline_major=35;
spline_minor=27.5;
spline_count=12;
// Belarus 1523.4 spline length 78mm
spline_length=80;

spline2_major=48;
spline2_minor=41.5;
spline2_count=16;
// Belarus 1523.4 spline2 length 30mm, but we need more as handle
spline2_length=60;

// Bearing iD = 25
pilot_diam=25;
pilot_guide_length_percent=20;
pilot_length=15;

// Not really useful for 1523.4
handle_length=0;

total_length = spline2_length+spline_length+handle_length+pilot_length;
echo (concat("Total length: ", total_length));

// 1523.4 clutch mechanism (splines) is about 110mm in length
usable_length = spline2_length+spline_length;
echo (concat("Total spline length: ", usable_length));

// HANDLE
cylinder(r=spline2_major/2, h=handle_length);

// BOTTOM SPLINE
translate([0,0,handle_length+spline2_length])
    spline(spline_major, spline_minor, spline_count, spline_length);
// TOP SPLINE
translate([0,0,handle_length])
    spline(spline2_major, spline2_minor, spline2_count, spline2_length);

// PILOT GENERATION
offset_pilot=handle_length+spline2_length+spline_length;
translate([0,0,offset_pilot])
     cylinder(r=pilot_diam/2, h=pilot_length*(1-pilot_guide_length_percent*0.01));
translate([0,0,offset_pilot+pilot_length*(1-pilot_guide_length_percent*0.01)])
     cylinder(r1=pilot_diam/2, r2=0.9*pilot_diam/2, h=pilot_length*(pilot_guide_length_percent*0.01));

module spline(spline_major=45, spline_minor=40, spline_count=20, spline_length=10){
    spline_depth=(spline_major-spline_minor)/2;
    major_circumference=3.14159*spline_major;
    minor_circumference=3.14159*spline_minor;

    spline_bottom_width=minor_circumference/(spline_count*2);
    spline_width=(major_circumference-(spline_bottom_width*spline_count))/spline_count;

    union() {
		difference() {
			cylinder(r=spline_major/2, h=spline_length);

			for (c=[0:spline_count])
				rotate([0,0,c*360/spline_count])
					translate([spline_minor/2+0.001,0,-0.5])
						linear_extrude(height=spline_length+1)
							polygon(points=[[0,-spline_bottom_width/2],[spline_depth,-spline_width/2],[spline_depth,spline_width/2],[0,spline_bottom_width/2]]);
		}
	}
}

```


[User]
I'm looking to generate some custom sprockets, and I've seen some existing code but it's not quite as flexible as I'd like. I need to be able to specify the number of teeth, roller diameter, thickness, pitch, and a tolerance for the roller fit. I also need to add a shaft attachment with a specified shaft diameter, hole diameter, and top and bottom heights for the shaft attachment feature. It also needs to have `$fs` and `$fa` variables defined to allow customization using the `cylinder()`'s `$fs` and `$fa` variables. I want to be able to generate idler sprockets as well, so it should be easy to change the parameters and re-render.

I think the approach is to generate the base sprocket shape using a `difference()` to cut out the spaces between teeth and also the roller pockets from a base cylinder. Then add the shaft attachments as additional cylinders on top and bottom, finally removing the center hole. I'd like the code to be clean and easy to understand, with good comments. I will also be 3D-printing these, so the default `fs` and `fa` values should be reasonable for 3D printing, i.e. $fs=1$ and $fa=7$.

Specifically, I'd like the output to consist of two files: one file named `sprocket_base.scad` which should contain a module called `sprocket` which handles only the generation of the tooth geometry and roller pockets, taking parameters as described above. The other file, named `sprocket_assembly.scad` should include `sprocket_base.scad` and assemble the base sprocket with the shaft attachments and center hole. I don't need any extra libraries, just good clean, readable OpenSCAD code.

[Assistant]
sprocket_generator1.2.scad:
```
// Sprocket generator v1

/* [Sprocket] */

// Example for 08B roller chain
teeth=10;
roller_d=8.51;
thickness=7.0; // 7.75 original 08B
pitch=12.70; // 12.7
tolerance=0.1;

/* [Shaft] */
shaft_d=22;
hole_d=16.5;
top_h=5;
bot_h=5;

/* [FS, FA] */
fs = 1;
fa = 7;

module sprocket(teeth=20, roller=3, pitch=17, thickness=3, tolerance=0.2){
	roller=roller/2; //We need radius in our calculations, not diameter
	distance_from_center=pitch/(2*sin(180/teeth));
	echo(distance_from_center);
	angle=(360/teeth);

    pitch_circle=sqrt((distance_from_center*distance_from_center) - (pitch*(roller+tolerance))+((roller+tolerance)*(roller+tolerance)));

    echo(pitch_circle);

    difference(){
		union(){
            $fs=fs;
            $fa=fa;
			cylinder(r=pitch_circle,h=thickness);
			for(tooth=[1:teeth]){
				intersection(){
					rotate(a=[0,0,angle*(tooth+0.5)]){
						translate([distance_from_center,0,0]){
                            $fs=fs;
                            $fa=fa;
							cylinder(r=pitch-roller-tolerance,h=thickness);
						}
					}
					rotate(a=[0,0,angle*(tooth-0.5)]){
						translate([distance_from_center,0,0]){
							cylinder(r=pitch-roller-tolerance,h=thickness);
						}
					}
				}
			}
		}
		for(tooth=[1:teeth]){
			rotate(a=[0,0,angle*(tooth+0.5)]){
				translate([distance_from_center,0,-1]){
					$fs=fs;
                    $fa=fa;
                    cylinder(r=roller+tolerance,h=thickness+2);
				}
			}
		}
	}
}

difference(){
    union(){
        sprocket(teeth,roller_d,pitch,thickness,tolerance);
        translate([0,0,thickness])
            cylinder(top_h,shaft_d/2,shaft_d/2,$fs=fs, $fa=fa); // TOP
        rotate([0,180])
            cylinder(bot_h,shaft_d/2,shaft_d/2,$fs=fs, $fa=fa); // BOT
    }
    translate([0,0,-bot_h-1]){ // Added -1 to make clean hole
        cylinder(bot_h+thickness+top_h+2,hole_d/2,hole_d/2,$fs=fs, $fa=fa);
    }
}
```


[User]
Okay, I'm looking for a parametric OpenSCAD design for a checker piece. I've got a basic idea, but I need the ability to adjust the dimensions.

Here's the breakdown of what I'm imagining:

**Base:**

*   The checker will have a cylindrical base.
*   I need to be able to set the diameter of the base (`base_diameter`) and the thickness (`base_thickness`).
*   There will be a small circular cut-out on the bottom of the base, like a little inset. I'd like to control the radius of this circular inset (`bottom_inset_radius`). It should be slightly offset from the edge of the base.
*   I want the inset to have a flat bottom, not a rounded one. I think I can achieve this by cutting out a square and circular area from the base.
*   I need to control the `fn` variable too, as I'm hoping for smooth curves.

**Top Details:**

*   On top of the base, I'd like a slightly raised circular element - like a dome but a truncated dome.
*   The diameter of the circular raised part needs to be parametric (`top_radius`). This will sit centered in the base.
*   I want this top element to have a smooth, rounded profile. I need to be able to control the `fn` variable for this too.
*   There's going to be an angled profile connecting the base to the raised dome, it should also have a smooth profile.
*   Finally, there's a little semi-spherical part centered on top of everything. I need to be able to control the diameter of this as well (`top_sphere_diameter`).

**Parametric Requirements:**

*   I need parameters for:
    *   `base_diameter`
    *   `base_thickness`
    *   `bottom_inset_radius`
    *   `top_radius`
    *   `top_sphere_diameter`
    *  `fn` (for curve smoothness)
*   The design should be fully parametric, meaning all dimensions and shapes should be controlled by these variables.

I'm not really sure where to start with the maths for connecting the different pieces, I hope you can help. Let me know if you need any more clarification, but that's the gist of it. I'd prefer if it didn't require external libraries as I'm trying to keep it simple, thanks.

[Assistant]
Checker.scad:
```
//Checker base diameter
a = 26;
//Checker base thickness
b = 1;
//Bottom radius
r1 = 5;
//Top radius
r7 = 1;//[0.5:0.5:5.0]

fn=100; // [6.0:2.0:100.0]

r5 = r1*(sqrt(2)-1);

difference(){
union(){
    translate([0,0,b]) rotate_extrude(convexity = 10, $fn = fn)

    difference(){
        translate([0.5*a-r1, 0, 0]) circle(r = r1, $fn = fn);
        translate([-2*r1,-r1,0]) square([2*r1,2*r1],center=false);
        translate([0.5*a-r1-r1,-2*r1,0]) square([2*r1,2*r1],center=false);
    }

    translate([0,0,b+(r1+2*r5+r7)/sqrt(2)])
        rotate_extrude(convexity = 10, $fn = fn)
            translate([a/2-(r5+r7)/sqrt(2), 0, 0])
                circle(r = r7, $fn = fn);

    cylinder(h = b, d=a, $fn = fn);

    translate([0,0,0])
        rotate_extrude(convexity = 10, $fn = fn)
            square([a/2-r5/sqrt(2),b+(r1+2*r5+2*r7)/sqrt(2)], $fn = fn);
}

translate([0,0,b+(r1+r5)/sqrt(2)])
        rotate_extrude(convexity = 10, $fn = fn)
            translate([a/2, 0, 0])
                circle(r = r5, $fn = fn);

translate([0,0,b+r1+a/2]) sphere(r=a/2*sqrt(2)-r5-2*r7,$fn = fn);
}
```


[User]
I'm looking to design a customizable box, specifically for playing cards, using OpenSCAD. I need it to be parametric so I can easily adjust the dimensions and some stylistic aspects.

The box should consist of two parts: a base and a lid. Both parts will have a honeycomb pattern on their faces (but not necessarily on the top or bottom of the lid or base). The honeycomb pattern should be customizable in terms of the shape of the cells (number of sides – from triangle to circle) as well as cell size, and overlap. It should also have a customizable rotation. The box itself should have adjustable width, height, and length parameters. There should be a parameter for the box wall thickness. The lid should fit snugly onto the base, with a tolerance adjustment parameter. Finally, the lid should have a customizable top height. It should also be able to be viewed with the honeycomb pattern alone, for testing. I'm envisioning two different view modes - one where it shows the base and lid together, and another where it just shows a sheet of the honeycomb pattern.

For the honeycomb pattern, I'd like to specify the cell shape with a parameter – options should be at least triangle, square, pentagon, hexagon, heptagon, octagon, nonagon, decagon, hendecagon, dodecagon, and a circle (which I understand you would approximate with a polygon having a large number of sides). Cell size and overlap should also be customizable in mm, as well as the cell rotation (in degrees). The thickness of the honeycomb structure should also be adjustable in increments of .4mm. The tolerance between the lid and base lip should also be adjustable in mm.

The overall box should have customizable length, width, height, lip height, and top height. These should all be specified in mm.

I’d like the design to utilize the `linear_extrude` and `intersection` commands, similar to the provided example code. Also, I will need some basic functionality to be able to cut the lip for the box (and lid) so the lip can fit together correctly.

Please provide the code in multiple files, with the main file being named `cardBox.scad` and a helper library file called `honeycomb.scad`, and I would prefer if the `honeycomb.scad` file would generate the `honeycombwall()` and `honeycomb()` modules I specified. I also need the `reinforce()` module to be included within `cardBox.scad`.

I don't think I need any specific libraries for this design.

[Assistant]
cardBox_v3scad.scad:
```
// Author: K1nc41d
// http://www.thingiverse.com/thing:38001

/*Customizer Variables*/

/*[Box]*/
//in mm:
case_thickness = 4; //[2:10]
//17mm per deck:
case_Width = 17; //[5:500]
case_Height = 74; //[25:500]
case_Length = 56; //[5:500]
case_Lip = 7; //[2:15]
case_Top_Height = 24; //[15:100]
//top fit in mm:
case_Lip_Tollerance = .25;

/*[Pattern]*/
pattern_shape = 6; //[3:Triangle (3-sided),4:Square (4-sided),5:Pentagon (5-sided),6:Hexagon (6-sided),7:Heptagon (7-sided),8:Octogon (8-sided),9:Nonagon (9-sided),10:Decagon (10-sided),11:Hendecagon (11-sided),12:Dodecagon (12-sided),30:Circle (30-sided)]
//in mm:
pattern_radius = 6; //[4:22]
pattern_overlap = 28; //[0:100]
//in degrees:
pattern_rotation = 21; //[0:180]
//in .4 mm increments:
pattern_thickness = 6; //[2:30]

/*[Hidden]*/

preview_tab = "Box";

honeycomb_thickness = pattern_thickness*.4;
BoxHeight = case_Height+case_thickness/2;
BoxLength = case_Length+case_thickness;
BoxWidth = case_Width+case_thickness;
BoxLip = case_Lip;
topHeight = case_Top_Height+case_thickness/2;

if(preview_tab == "Box"){
        translate([0,0,case_thickness/2])
		difference(){
            baseBox();
            boxLipCut();
        }
        translate([0,BoxWidth*2+case_thickness,case_thickness/2])
        difference(){
            topBox();
            boxTopLipCut();
        }
	}
    else {
        honeycombwall(BoxLength,BoxHeight,case_thickness,pattern_radius,pattern_overlap,honeycomb_thickness,pattern_shape,pattern_rotation);
    }

module boxTopLipCut(){
    translate([-(BoxLength+case_thickness)/2, -(BoxWidth+case_thickness)/2,case_thickness/2])
    cube([BoxLength+case_thickness,BoxWidth+case_thickness,topHeight+1]);
}

module topBox(){
    length = BoxLength + 2*case_thickness;
    width = BoxWidth + 2*case_thickness;
    height = topHeight + case_thickness;
    union(){
       //bottom
        honeycombwall(length,width,case_thickness,pattern_radius,pattern_overlap,honeycomb_thickness,pattern_shape,pattern_rotation);
        //front
        translate([0,(BoxWidth+case_thickness)/2,topHeight/2])
        rotate([90,0,0])
        honeycombwall(length,height,case_thickness,pattern_radius,pattern_overlap,honeycomb_thickness,pattern_shape,pattern_rotation);
        //Back
        translate([0,-(BoxWidth+case_thickness)/2,topHeight/2])
        rotate([90,0,0])
        honeycombwall(length,height,case_thickness,pattern_radius,pattern_overlap,honeycomb_thickness,pattern_shape,pattern_rotation);
    }
    //left
        translate([(BoxLength+case_thickness)/2,0,topHeight/2])
        rotate([90,0,90])
        honeycombwall(width,height,case_thickness,pattern_radius,pattern_overlap,honeycomb_thickness,pattern_shape,pattern_rotation);
    //right
        translate([-(BoxLength+case_thickness)/2,0,topHeight/2])
        rotate([90,0,90])
        honeycombwall(width,height,case_thickness,pattern_radius,pattern_overlap,honeycomb_thickness,pattern_shape,pattern_rotation);
    reinforce(length,width,height,0);
}

module baseBox(){
    length = BoxLength + 2*case_thickness;
    width = BoxWidth + 2*case_thickness;
    height = BoxHeight + case_thickness;
    union(){
       //bottom
        honeycombwall(length,width,case_thickness,pattern_radius,pattern_overlap,honeycomb_thickness,pattern_shape,pattern_rotation);
        //front
        translate([0,(BoxWidth+case_thickness)/2,BoxHeight/2])
        rotate([90,0,0])
        honeycombwall(length,height,case_thickness,pattern_radius,pattern_overlap,honeycomb_thickness,pattern_shape,pattern_rotation);
        //Back
        translate([0,-(BoxWidth+case_thickness)/2,BoxHeight/2])
        rotate([90,0,0])
        honeycombwall(length,height,case_thickness,pattern_radius,pattern_overlap,honeycomb_thickness,pattern_shape,pattern_rotation);
    }
    //left
        translate([(BoxLength+case_thickness)/2,0,BoxHeight/2])
        rotate([90,0,90])
        honeycombwall(width,height,case_thickness,pattern_radius,pattern_overlap,honeycomb_thickness,pattern_shape,pattern_rotation);
    //right
        translate([-(BoxLength+case_thickness)/2,0,BoxHeight/2])
        rotate([90,0,90])
        honeycombwall(width,height,case_thickness,pattern_radius,pattern_overlap,honeycomb_thickness,pattern_shape,pattern_rotation);
    reinforce(length,width,height,BoxLip);
}

module boxLipCut(){
    length = BoxLength + 2*case_thickness;
    width = BoxWidth + 2*case_thickness;
    translate([-(length/2+1),-(width/2+1),BoxHeight+case_thickness/2-BoxLip]){
        difference(){
            cube([length+2,width+2,BoxLip+2]);
            translate([case_thickness/2+1+case_Lip_Tollerance/2,case_thickness/2+1+case_Lip_Tollerance/2,-1])cube([(length - case_thickness)-case_Lip_Tollerance, (width - case_thickness)-case_Lip_Tollerance, BoxLip+4]);
        }
    }
}

module reinforce(l,w,h,topadd){
    translate([-l/2,-w/2,-case_thickness/2])
    difference(){
        cube([l,w,h]);
        union(){
        translate([case_thickness, case_thickness, -1])cube([l-(case_thickness*2),w-(case_thickness*2),h+2]);
        translate([-1, case_thickness, case_thickness])cube([l+2,w-(case_thickness*2),h-(case_thickness*2+topadd)]);
        translate([case_thickness, -1, case_thickness])cube([l-(case_thickness*2),w+2,h-(case_thickness*2+topadd)]);    }
    }
}

module honeycombwall(w,l,h,rad,radmod,thickness,sides,rot){
    linear_extrude(h, center = true, convexity = 10)intersection(){
    honeycomb(w,l,rad,radmod,thickness,sides,rot);
    translate([-(w/2),-(l/2),0])square([w,l]);
    }
}

module honeycomb(w,l,r,rmod,th,sides,rot){
    fudge = .05;
	columns = l/(r*3)+1;
	rows = w/(r*sqrt(3)/2*2);

	translate([-w/2,l/2,0])
		rotate([0,0,-90])

			for(i = [-1:rows+1]){

				translate([0,r*sqrt(3)/2*i*2,0])
					for(i = [0:columns]){
						translate([r*i*3,0,0])
							for(i = [0:1]){
								translate([r*1.5*i,r*sqrt(3)/2*i,0])
									rotate([0,0,rot])
									difference(){
										if(sides < 5){
											circle(r = r+th+(r*rmod/50)+fudge, center = true, $fn = sides);
										} else {
											circle(r = r+(r*rmod/50)+fudge, center = true, $fn = sides);
										}
										circle(r = r-th+(r*rmod/50), center = true, $fn = sides);
									}
							}
					}
			}
}

```


[User]
I'd like to create a parametric OpenSCAD design for building frames for tabletop gaming tiles, similar to the OpenForge Smooth Multifloor Frames. I need it to be flexible, so I can create frames with different sizes and edge conditions.

Here are the key requirements:

*   **Tile Size:** The frame should support tiles that are made up of multiple elements, each element being a 25x25 mm square.
*   **Element Dimensions:** I need to be able to control the size of the individual tile elements used in the frame. I need to be able to set `element_x` and `element_y` values to define the dimensions of the base tile.
*   **Frame Dimensions:** The frame should support multiple rows and columns of these tile elements. I need to be able to specify the `rows` and `columns` of the frame. So, I could set, say, 2x2 tiles for a 2x2 frame to get a larger 2x2 tile frame.
*   **Edge Customization:** I also need to customize the edges of the frame. I should be able to choose which edges to extend to allow for the frame to be used as an edge tile or a normal tile. I need to be able to set `left_edge`, `right_edge`, `front_edge`, and `back_edge` to true or false values. When an edge is true, I want to extend that edge to create an extended border that will allow it to connect to other frame tiles. If the edge is false, then it should be a "normal" edge with a thinner border.
*   **OpenSCAD Implementation:** I need the design to be implemented in OpenSCAD, using standard OpenSCAD primitives and not relying on any libraries, so that it's easy to port across different systems and be easily modifiable.

Basically, I want to be able to set the element size, the frame size in elements, and which edges to extend. I want to be able to set `element_x`, `element_y`, `rows`, `columns`, `left_edge`, `right_edge`, `front_edge`, and `back_edge`. I don't need to use any particular libraries for this, standard OpenSCAD should do just fine. Can you generate the OpenSCAD code for this?

[Assistant]
square_frame_customizer.scad:
```
element_x = 2; // [1,2,3,4,5,6]
element_y = 2; // [1,2,3,4,5,6]
rows = 2; // [1,2,3,4,5,6]
columns = 2; // [1,2,3,4,5,6]
left_edge = "false"; // [false,true]
right_edge = "false"; // [false,true]
front_edge = "false"; // [false,true]
back_edge = "false"; // [false,true]

module frame_square(x,y,l,r,f,b) {
  difference() {
    union() {
      translate([-l,-f,0]) cube([25*x+r+l,25*y+f+b,7.5]);
    }
    translate([3.6-l,3.6-f,-0.1]) cube([25*x+r+l-7.2,25*y+f+b-7.2,10]);
    for(i = [0 : x-1]) {
      translate([12.5+i*25,-5-f,3.75]) rotate([270,0,0]) cylinder(31*y+f+b,.75,.75,$fn=50);
      translate([12.5+i*25,3.6-f,-.1]) rotate([0,0,0]) cylinder(3.85,.75,.75,$fn=50);
      translate([12.5+i*25,25*y-3.6+b,-.1]) rotate([0,0,0]) cylinder(3.85,.75,.75,$fn=50);
    }
    for(i = [0 : y-1]) {
      translate([-5-l,12.5+i*25,3.75]) rotate([0,90,0]) cylinder(31*x+r+l,.75,.75,$fn=50);
      translate([3.6-l,12.5+i*25,-.1]) rotate([0,0,0]) cylinder(3.85,.75,.75,$fn=50);
      translate([25*x-3.6+r,12.5+i*25,-.1]) rotate([0,0,0]) cylinder(3.85,.75,.75,$fn=50);
    }
  }
}

module frame(x, y, rows, cols, ledge="false", redge="false", fedge="false", bedge="false", border=9.2) {
    for(i = [0 : rows-1]) {
        for(j = [0 : cols-1]) {
            translate([25*x*i,25*y*j,0]) frame_square(
                x,y,
                i>0 ? .1:i==0 && ledge == "true" ? border:0,
                i == rows-1 && redge == "true" ? border:0,
                j>0 ? .1:j==0 && fedge == "true" ? border:0,
                j == cols-1 && bedge == "true" ? border:0);
        }
    }
}

frame(element_x,element_y,rows,columns, ledge=left_edge,redge=right_edge,fedge=front_edge,bedge=back_edge);
```


[User]
Hey, I'm looking to create a parametric design for a handlebar-mounted cup holder for my motorcycle. I need it to be adjustable for different handlebar diameters and be fairly robust. I've got a basic concept in mind, but I need help making it parametric and easier to customize.

Here’s what I’m thinking:

**Overall Structure:**

*   The cup holder will consist of three main parts: a handlebar mount, a swivel mount, and the actual cup holder body.
*   The cup holder should be able to rotate on the swivel mount for adjustable positioning, with that being held in place by two M3 bolts.
*   The handlebar mount will clamp onto the handlebars using two M5 bolts and locknuts.
*   The cup holder body will be cylindrical with some cutouts for aesthetics or weight reduction, and a lip at the top.

**Handlebar Mount:**

*   It needs to clamp onto the handlebars using two M5 bolts and locknuts. The design will need to be split with a cutout to accommodate various handlebar diameters and then tightened down with the bolts.
*   The clamp should be adjustable for different handlebar diameters and handlebar widths (where it mounts perpendicular to the bar).
*   The clamp should have recesses for the M5 bolt heads and locknuts.
*   It will need two M3 holes to attach the swivel mount and cup holder with one M3 locknut to secure the assembly.

**Swivel Mount:**

*   This part needs to connect the handlebar mount to the cup holder and allow the cup holder to rotate.
*   It should be a C-shaped piece with a cylindrical cutout in the middle to rotate around the M3 bolt.
*   It should have two M3 bolt holes on either end to connect with the handlebar mount and cup holder.
*   It should also have locknut traps for the mounting M3 bolts.

**Cup Holder Body:**

*   The cup holder should be a cylinder with a defined inner and outer diameter and height, this will need to be customizable.
*   It should have a lip or ring at the top.
*   It should have some cutouts along the side for weight reduction.
*   It will have an M3 through hole to connect with the swivel mount on one side, with a depression for the M3 bolt head on the other side.

**Parametric Requirements:**

*   Handlebar diameter (in inches)
*   Clamp width (in inches)
*   Clamp thickness (in inches)
*   Cup holder height, inner diameter and outer diameter, as well as top ring height
*   Swivel height, inner diameter and outer diameter
*   M3 and M5 bolt and locknut dimensions

**Additional Notes:**

*   I'd like to use the BOLTS library for the bolt and nut dimensions.
*   I'm looking for a robust design, so think about the stresses involved.
*   I don’t need threads on the parts, just holes sized appropriately for the bolts. The model will be 3D printed and then fasteners will be used for the assembly.
*   I'd like the code to be well-commented so I can easily understand and modify it.
*   I'd like a bit of slop included to allow parts to move together well.

Could you generate an OpenSCAD file (or files if that makes more sense) to achieve this? Let me know if you need any more clarification.

[Assistant]
handlebar_cup_holder.scad:
```
/* [Hidden] */
inch=25.4;
slop=0.2;
m5_head_rad=5+slop;
m5_thread_rad=2.5+slop;
m5_thread_thickness=.8;
m5_locknut_height=5;
m5_locknut_rad=(8/cos(180/6))/2;
m3_thread_rad=2;
m3_locknut_height=4;
m3_locknut_width=5.5/cos(180/6);
m3_head_height=1.65+slop;
m3_head_width=5.5+slop;
$fn=360;
cupholder_height=114;
cupholder_top_ring_height=10;
cupholder_bottom_thickness=5;
cupholder_inner_diam=87;
cupholder_outer_diam=95;
cupholder_slot_width=8;
cupholder_slot_height=99;
cupholder_slot_cutout_width=112;
swivel_inner_diam=101;
swivel_outer_diam=115;
swivel_height=10;

/* [Mount] */
// Radius of the handlebar in inches
radius = 0.5;
bar_rad=radius*inch;
// Width of the clamp in inches
clamp_width=0.75;
mount_width=clamp_width*inch;
// Thickness of the clamp in inches
clamp_thickness=0.75;
mount_thickness=clamp_thickness*inch;
// How much of the center is cut off to ensure tight fit around bars in millimeters
halves_separation=3;

translate([cupholder_outer_diam/2+mount_thickness+bar_rad+5,0,mount_width/2])
handlebar_mount();

cup_holder(cupholder_inner_diam/2, cupholder_outer_diam/2, cupholder_height);
//translate([0,0,104])
rotate([0,0,-96.5])
swivel_mount(swivel_inner_diam/2, swivel_outer_diam/2, swivel_height);

module swivel_mount(inner_r, outer_r, height){
    translate([0,0,swivel_height/2])
    difference() {
            // Make C shape
        union() {
            for(i = [-outer_r,inner_r]) {
                translate([i,0,-height/2]) cube([outer_r-inner_r, 5,height]);
            }
            difference() {
                cylinder(h=height, r=outer_r, center=true);
                cylinder(h=height+slop, r=inner_r, center=true);
                translate([-outer_r-slop,0,-height]) cube([(outer_r+slop)*2, outer_r+slop,height*2]);

            }
        }
        // Make M3 holes and locknut traps
        rotate([0,90,0]) cylinder(h=2*outer_r+slop,r=m3_thread_rad,center=true);
        for (i = [-1,1]) {
            translate([i*(outer_r-.5), 0, 0]) rotate([0,i*270,0]) cylinder(h=m3_locknut_height*2, r1=m3_locknut_width/2+slop*2, r2=m3_locknut_width/2-slop, $fn=6,center=true);
        }
        rotate([90,0,0]) cylinder(h=2*(inner_r+m3_head_height), r=m3_head_width/2, center=true);
        rotate([90,0,0]) cylinder(h=outer_r*2, r=m3_thread_rad, center=true);
    }
}
module cup_holder(inner_r, outer_r, height){
    difference() {
        // cupholder
        cylinder(h=height, r=outer_r);      translate([0,0,5]) cylinder(h=height, r=inner_r);
        // side wall cutouts
        translate([0,0,5])
        for (i = [0:15]){
            rotate([0,0,i*22.5])
            cube([cupholder_slot_cutout_width, cupholder_slot_width,cupholder_slot_height]);
        }
        // M3 hole cutouts
        translate([0,0,109]) rotate([90,0,-6.5]) cylinder(h=cupholder_slot_cutout_width, r=m3_thread_rad,center=true);

        // M3 head depression
        translate([0,0,109]) rotate([90,0,-6.5]) cylinder(2*(inner_r+m3_head_height), r=m3_head_width/2,center=true);
    }
}

module handlebar_mount() {
    difference() {
        base_object();

        // handlebar cutout
        cylinder(h=mount_width+slop, r=bar_rad+slop, center=true);
        cube([halves_separation,2*(bar_rad+mount_thickness+slop)+slop,mount_width+slop],center=true);

        // M5 Hole cutouts
        for(i = [-1,1]){
            translate([0,i*(bar_rad+5+m5_thread_rad+slop), 0]) rotate([0,90,0]) cylinder(h=mount_width*3+slop,r=m5_thread_rad,center=true);
        }

        // Socket Head Cutouts
        for(i = [-1,1]){
            translate([6.5, i*(bar_rad+2.5+slop+m5_head_rad),0]) rotate([0,90,0]) cylinder(h=mount_width*2+slop,r=m5_head_rad+slop);
        }

        // M5 Locknut Cutouts
        for(i = [-1,1]){
            translate([-6.5,i*(bar_rad+3+slop+m5_locknut_rad), 0]) rotate([0,270,0]) cylinder(h=mount_width*2,r1=m5_locknut_rad-slop,r2=m5_locknut_rad+slop*2,$fn=6);
        }

        // M3 Hole cutout
        translate([bar_rad+mount_thickness+slop-5, bar_rad+mount_thickness+slop, 0]) rotate([90,00,0]) cylinder(h=20, r=m3_thread_rad+slop, center=true);

        // M3 Locknut Cutout
        translate([bar_rad+mount_thickness+slop-5, bar_rad+mount_thickness+slop-m3_locknut_height-1, 0]) rotate([90,0,0]) cylinder(h=m3_locknut_height+2, r1=m3_locknut_width/2-slop,r2=m3_locknut_width/2+slop*2, $fn=6, center=true);

        // Trim back side of mount
        rotate([0,0,270])
        translate([mount_width+bar_rad, 0, -slop/2])
        cube([mount_width/2,mount_width*3+slop,mount_thickness+slop*2], center=true);

        // Just to make sure locknut doesn't impede M5 bolt
    %translate([bar_rad+mount_thickness+slop-5, bar_rad+mount_thickness+slop-m3_locknut_height, 0]) rotate([90,0,0]) cylinder(h=m3_locknut_height+slop, r=m3_locknut_width/2+slop, $fn=6, center=true);
    }
}

module base_object(){
    union(){
        cylinder(h=mount_width, r=bar_rad+mount_thickness+slop, center=true);
        translate([0,0,-(mount_width)/2])
        cube([bar_rad+mount_thickness+slop, bar_rad+mount_thickness+slop,mount_width]);
    }
}

```


[User]
I need an OpenSCAD design for a GPS dome that fits on top of a standard 30.5 x 30.5mm flight controller. I want it to have a customizable dome height and a top plate. The top plate should have screw holes for mounting, and those screw holes should have countersinks for the screw heads. I'd also like to optionally add a chamfer to the top of those screw holes.

The design should also include an optional intermediate plate that can be glued to the dome, with a gap between the two, and this also needs to be customizable for height and have an optional hole. The dome legs should also be reinforced.

I need to be able to specify the following parameters:
-   Footprint hole distance (fhd) - should be 30.5mm as default
-   Dome height (h_dome)
-   Top plate thickness (h_Plate)
-   Plate border height (h_Bord)
-   Weight reduction hole diameter on top (tophole_dia)
-   Cylinder outer diameter for the dome legs (Cyl_Dia)
-   Cylinder segment wall thickness (Cyl_Wall)
-   Screw hole diameter (M3_Dia)
-   Screw head sink diameter (M3_Sink_dia)
-   Screw head sink depth (M3_Sink_ht)
-   Screw head hole chamfer depth (M3_Head_Chamfer)
-   Intermediate level plate Z position (z_level)
-   Intermediate level plate thickness (h_level)
-   Gap between domes and level plate (Gap_level)
-   Weight reduction hole diameter on intermediate plate (level_dia)

I'd like to be able to toggle whether I'm printing just the top part, just the intermediate level, or both. I would also like an option to include support structures for the screw domes to better print overhangs.

I would like the scad files to be completely parametric and without needing any additional libraries. I think the "hull" function will work well for this!

[Assistant]
10-24_GPS-Dome.scad:
```
//**********************************************
//       GPS Cover Dome for Quadcopter 30.5 x 30.5mm FC
//  Source Code and created objects are free for private use
//              (C) Henning Stöcklein   18.10.2015

//********** Change log **********************************
// 18.10.2015   Created as split off my FNQ Foldable Quadcopter Source
// 24.10.2015   Screw top head chamfer added, optional top hole added
//********** End Change log *******************************

/* [Object Selection] */

// What to print
visible = "all" ; // ["all", "top plate", "level plate"]

// Support Structure
Support = 0 ;  // [0:No, 1:Yes]

/* [Base geometry] */

// Footprint Hole Distance
fhd = 30.5 ;

// Dome height
h_dome = 18.0; // [8:30]

// Top Plate thickness
h_Plate = 1.0 ;

// Plate Border height
h_Bord = 2.0 ;

// Weight reduction hole diameter
tophole_dia = 0 ; // [0:28]

// Cylinder Outer Diameter
Cyl_Dia = 5.5 ;

// Cylinder Segment Wall Thickness
Cyl_Wall = 1.2 ;

// Screw Hole Diameter
M3_Dia = 3.5 ;

// Screw Head Sink Diameter
M3_Sink_dia = 5.9 ;

// Screw Head Sink Depth (0=Flat on top)
M3_Sink_ht = 10 ;

// Screw Head Hole Chamfer depth
M3_Head_Chamfer = 0.2 ;

/* [Intermediate plate] */

// Level plate Z position
z_level = 9 ; // [9:22]

// Level plate thickness
h_level = 1.1 ;

// Gap between domes and level plate
Gap_level = 0.2 ;

// Weight reduction hole diameter
level_dia = 22 ; // [0:28]

//*******************************************
//*  Select here what to print
//*******************************************
if (visible == "all") {
    coverdome() ;
    levelplate() ;
}

if (visible == "top plate") {
    coverdome() ;
}

if (visible == "level plate") {
    levelplate() ;
}

// *************************************************
//    Cover dome for 30.5 x 30.5 FC footprint
// *************************************************
module coverdome()
{
   // Holder for FC footprint 30.5x30.5 (e.g. Naze32)
   difference() {
      union() {
		// Top plate = Round cube
        translate ([0,0,h_dome])
          hull() {
            translate ([+fhd/2,+fhd/2,0]) cylinder (r=Cyl_Dia/2, h=h_Plate, $fn=20) ;
            translate ([+fhd/2,-fhd/2,0]) cylinder (r=Cyl_Dia/2, h=h_Plate, $fn=20) ;
            translate ([-fhd/2,+fhd/2,0]) cylinder (r=Cyl_Dia/2, h=h_Plate, $fn=20) ;
            translate ([-fhd/2,-fhd/2,0]) cylinder (r=Cyl_Dia/2, h=h_Plate, $fn=20) ;
        } // hull

        // 4 cylindrical legs with screw holes
        for (i=[0:90:350])
        {
            rotate ([0,0,i])
            {
        		// Domes for M3 screws
                translate ([+fhd/2,+fhd/2,0]) cylinder (r=Cyl_Dia/2, h=h_dome, $fn=20) ;

        	    // Small side wall
                translate ([0,+fhd/2+Cyl_Dia/2-h_Plate/2,h_dome-h_Plate/2])
                    cube ([fhd, h_Plate, h_Bord], center=true) ;

         		// Dome strengthening segments
                hull ()
                {
                intersection () {
                     translate ([+fhd/2,+fhd/2,h_dome+h_Plate-M3_Sink_ht])
                        cylinder (r=Cyl_Wall+Cyl_Dia/2, h=M3_Sink_ht, $fn=20) ;
                     hullplate() ;
                  } // intersection
                  translate ([+fhd/2,+fhd/2,h_dome+h_Plate-M3_Sink_ht-2.5])
                      cylinder (r=Cyl_Dia/2, h=0.1, $fn=20) ;
                 } // hull
             } // rotate
         } // for
      } // union

      // Cutout objects for 4 screw holes
      for (i=[0:90:350])
      {
          rotate ([0,0,i])
          {
        	  // Holes for M3 bolts
              translate ([+fhd/2,+fhd/2,0])
                  cylinder (r=M3_Dia/2, h=50, $fn=20, center=true) ;

        	  // Sink Holes for M3 heads
              translate ([+fhd/2,+fhd/2,h_dome+h_Plate-M3_Sink_ht])
                  cylinder (r=M3_Sink_dia/2, h=M3_Sink_ht+0.05, $fn=20) ;

        	  // Chamfer Cylinder for segmented area (if any)
              translate ([+fhd/2+M3_Sink_dia/2,+fhd/2+M3_Sink_dia/2,h_dome+h_Plate-M3_Sink_ht])
                  cylinder (r=M3_Sink_dia/1.25, h=M3_Sink_ht+0.05, $fn=20) ;

        	  // Chamfer Cylinder at top screw hole cutout (if any)
              translate ([+fhd/2,+fhd/2,h_dome+h_Plate-M3_Head_Chamfer])
                  cylinder (r1=M3_Sink_dia/2, r2=M3_Sink_dia/2+2, h=2, $fn=20) ;
          } // rotate
      } // for

      // Weight reduction hole
      translate ([0,0,h_dome]) cylinder (r=tophole_dia/2, h=h_Plate+3, $fn=40, center=true) ;

   } // difference

   // Support structure (if cutout legs)
   if (Support == 1) {
     for (i=[0:90:350])
     {
        rotate ([0,0,i])
        {
           translate ([+fhd/2+Cyl_Dia/3,+fhd/2+Cyl_Dia/3,h_dome+h_Plate-M3_Sink_ht])
               cylinder (r=0.8, h=M3_Sink_ht+0.05, $fn=20) ;
        } // rotate
    } // for
  } // if
}

//********************************************
// Additional plate can be fixed in the middle of the Domes
//********************************************
module levelplate()
{
   // Intermediate level to fix GPS module
   difference() {
      union() {
		// Plate = Round cube
        translate ([0,0,z_level])
          hull() {
            translate ([+fhd/2,+fhd/2,0]) cylinder (r=Cyl_Dia/2, h=h_level, $fn=20) ;
            translate ([+fhd/2,-fhd/2,0]) cylinder (r=Cyl_Dia/2, h=h_level, $fn=20) ;
            translate ([-fhd/2,+fhd/2,0]) cylinder (r=Cyl_Dia/2, h=h_level, $fn=20) ;
            translate ([-fhd/2,-fhd/2,0]) cylinder (r=Cyl_Dia/2, h=h_level, $fn=20) ;
        } // hull
      } // union

      // Weight reduction hole
      translate ([0,0,z_level]) cylinder (r=level_dia/2, h=h_level+2, $fn=40, center=true) ;

      // 4 cylindrical legs with screw holes
      for (i=[0:90:350])
      {
          rotate ([0,0,i])
          {
        		// Holes for Domes
                translate ([+fhd/2,+fhd/2,0])
                    cylinder (r=Cyl_Dia/2+Gap_level, h=h_dome, $fn=20) ;

                // Holes for Strengthening Dome Segments
                translate ([+fhd/2,+fhd/2,h_dome+h_Plate-M3_Sink_ht])
                     cylinder (r=Cyl_Wall+Cyl_Dia/2+Gap_level, h=M3_Sink_ht, $fn=20) ;
          } // rotate
      } // for
  } // difference
}

module hullplate()
{
    // Top plate = Round cube
    hull() {
            translate ([+fhd/2,+fhd/2,0]) cylinder (r=Cyl_Dia/2, h=40, $fn=20) ;
            translate ([+fhd/2,-fhd/2,0]) cylinder (r=Cyl_Dia/2, h=40, $fn=20) ;
            translate ([-fhd/2,+fhd/2,0]) cylinder (r=Cyl_Dia/2, h=40, $fn=20) ;
            translate ([-fhd/2,-fhd/2,0]) cylinder (r=Cyl_Dia/2, h=40, $fn=20) ;
   } // hull
}

```


[User]
Hey, I'm trying to design a cartridge holder for some old game cartridges, and I'm hoping you can help me generate the OpenSCAD code. I've got a basic idea, but I need it to be parametric so I can adjust it for different cartridge sizes and quantities.

Here's what I'm thinking:

*   **Cartridge Dimensions:** I need to define the width, depth, and the holding depth of a single cartridge as parameters. Let's call them `cartridgeX`, `cartridgeY`, and `holderDepth`, respectively.
*   **Number of Cartridges:** I'd like to specify how many cartridges the holder should hold with a parameter, let's call this one `numCartridges`.
*   **Wall Thickness:** The walls separating the cartridges should have a consistent thickness, parameterized as `wallWidth`.
*   **Stadium Shape:** I want the holder to have a kind of stepped or stadium-like shape, so the cartridges are displayed at different heights, making them easier to see and grab.

Essentially, I envision a series of 'stair steps' where each step holds a cartridge. I also need a hull (or 'subtract') to cut out the cartridge-shaped spaces.

So, to summarize, I'd like a parametric OpenSCAD design with these parameters:

*   `cartridgeX`: Cartridge width
*   `cartridgeY`: Cartridge depth
*   `holderDepth`: How deep the cartridge will sit in the holder
*   `numCartridges`: The number of cartridges the holder will hold
*   `wallWidth`: The thickness of walls separating each cartridge slot

Could you generate the OpenSCAD code for this, using modules where appropriate? I don't need to use any specific libraries.

[Assistant]
custimizableCartridgeHolder.scad:
```
// width of the cartridge
cartridgeX = 117;
// depth of the cartidge
cartridgeY = 21;
// how much of the cartridge will sit in the holder
holderDepth = 18;
// thickness of the walls between each game
wallWidth = 3;
// how many cartridges that you want to fit in the holder
numCartridges = 8;

module cartridge() {
	cube([cartridgeX,cartridgeY,holderDepth]);
}
module stadium(levels, width, stairsize) {
	for ( l = [0 : levels]) {
		translate([0,0,l*(stairsize/2)])
		cube([width, (levels*stairsize)-(l*stairsize), stairsize]);
	}

}
module hullcart(levels, width, stairsize) {
	for( l = [0: levels]) {
		translate([
			(width-cartridgeX)/2,
			(l*stairsize)+((stairsize-cartridgeY)/2),
			((levels-l)*stairsize/2)])
		cartridge();
	}
}

module cartridgeHolder(){
	difference() {
		stadium(numCartridges, cartridgeX + wallWidth, cartridgeY + wallWidth);
		hullcart(numCartridges, cartridgeX + wallWidth, cartridgeY + wallWidth);
	}
}

cartridgeHolder();
```


[User]
I'd like to create a parametric PTFE tube guide for my M3D printer. I have some of the design specs already figured out, but I need help generating the OpenSCAD code.

Here are the basic requirements:

*   It needs to have two main cylindrical holes. One will guide the PTFE tube, and the other will guide the M3D printer's cable.
*   The hole for the PTFE tube should be customizable in diameter, defaulting to 4.1mm.
*   The hole for the M3D cable should also be customizable, defaulting to 6mm.
*   The wall thickness around each hole should be adjustable and defaults to 1.5mm.
*   The length of the tube guide needs to be adjustable, defaulting to 8mm.
*   The distance between the centers of the two cylindrical holes should also be adjustable, defaulting to 4mm.
*   The design will have a rectangular "connector" section between the two cylindrical portions.
*   There should also be a wedge-shaped opening on the cable guide side of the part to make it easier to install the cable. It should have a 45-degree angle cut.

I'd like to be able to adjust all of these values as parameters in the OpenSCAD file. I'm not asking for complex shapes or anything, just basic cylindrical holes and a rectangular section connecting them. So, the basic shape is a cylinder -> rectangular prism -> cylinder with the appropriate holes subtracted from it along with the wedge cut.

I'm hoping you can create the OpenSCAD file that can generate this. I don't need any additional libraries for this design - just the basic OpenSCAD primitives. Thanks!

[Assistant]
M3D_PTFE_Guide.scad:
```
// M3D PTFE tube Holder
// Tony Hansen 2015
// Inspired by the filament guides <http://www.thingiverse.com/thing:858100>
// and <http://www.thingiverse.com/thing:865138>,
// which were designed to guide filament.
// This is instead sized to guide a 4mm PTFE tube
// and the values are customizable to any size.

// the hole where the PTFE tube goes
topHoleDiameter = 4.1;
// the M3D cable going to the print head
bottomHoleDiameter = 6;
// the filament thickness around the holes
wallThickness = 1.5;
// the length of the tube
tubeLength = 8;
// the distance between holes
distanceBetweenHoles = 4;

difference() {
    epsilon=0.1;
    union() {
        // Cylinder connecting to M3D Cable
        cylinder(d=bottomHoleDiameter + wallThickness * 2,h=tubeLength,$fn=50);

        // "square portion"
        translate([0,-topHoleDiameter/2-wallThickness,0])
        cube([bottomHoleDiameter/2 + topHoleDiameter/2 + distanceBetweenHoles + wallThickness,
            topHoleDiameter + 2*wallThickness, tubeLength]);

        // Top cylinder that holds the PTFE
        translate([bottomHoleDiameter/2+distanceBetweenHoles+topHoleDiameter/2+wallThickness,0,0])
            cylinder(d=topHoleDiameter+wallThickness*2, h=tubeLength, $fn=50);
    }

    // The hole for the M3D Cable
    translate([0,0,-epsilon])
        cylinder(d=bottomHoleDiameter,h=tubeLength+2*epsilon,$fn=50);

    // The hole for the PTFE tube
    translate([bottomHoleDiameter/2+distanceBetweenHoles+topHoleDiameter/2+wallThickness,
        0,0])
        translate([0,0,-epsilon])
        cylinder(d=topHoleDiameter, h=tubeLength+2*epsilon, $fn=50);

    // The wedge opening for the M3D Cable
    translate([-bottomHoleDiameter*7/8,0,0])
        rotate([0,0,45])
        translate([-bottomHoleDiameter/2,-bottomHoleDiameter/2,-epsilon])
        cube([bottomHoleDiameter,bottomHoleDiameter,tubeLength+2*epsilon]);
}
```


[User]
I'm looking to create a customizable platform that can attach to the rails of a standard optical cage system. I need something that can straddle two rails and provide a solid, flat surface above them to mount other components. The goal is to make it easily adaptable to different cage systems and component sizes, so I want to make it fully parametric.

Here’s what I have in mind:

*   **Rail Attachment:** The platform needs to securely grab onto two parallel cage rods. The grip should have good contact, but I don't want to over-constrain things. I think using a partial cylindrical grip would work - something like 180 degrees of a cylinder cut into a rectangular block. It needs to accommodate different rail diameters and spacings.
*   **Platform:** The main platform should be a rectangular block above the rails. This provides a mounting surface. The height should be adjustable so it can be raised to whatever height makes sense.
*   **Mounting Holes:** I need to be able to add mounting holes to the platform. These should be equally spaced and I should be able to control the number and diameter.
*   **Parameters:** Here's what I want to control via parameters:
    *   `length_x`: The length of the platform along the rails.
    *   `width_y`: The width of the platform across the rails.
    *   `height_z`: The height of the platform above the rails.
    *   `rail_diameter`: The diameter of the cage rods.
    *   `rail_spacing`: The distance between the centers of the cage rods.
    *   `number_of_holes`: The number of mounting holes on the platform.
    *   `hole_diameter`: The diameter of the mounting holes.

It'd also be great if the design was clean - a simple, but solid design is what I'm going for. I’d also like the mount to be mirrored, so it’s the same piece on either side of the rails. This part is critical.

Could you generate the OpenSCAD code for this, please? I don't need any specific OpenSCAD library included unless you think it will make things easier - something like `BOSL` or `BOSL2` would be okay if it makes the code simpler.

[Assistant]
parametric_cage_carrier.scad:
```
/*
 This creates a general purpose widget holder to stradle two rails on a cage system.
 The calculations are done such that the given Z height is entirely above the rails with additional material below and beside the rails.
 */

// length or x direction (length along the rail)
length_x = 100;
// Width or y direction (width across rails)
Width_y = 40;
// Height or z direction (height above rail)
Height_z = 6;

Rail_Diameter = 6;

Rail_Spacing = 26.9;

Number_of_Holes = 3; //[0:10]

Hole_Diameter = 6;
//nutSize = 8; //size of nuts

difference(){
    Put_Together();
    make_holes(Hole_Diameter);
}

module Put_Together(){
    union(){
        make_rodholder();
        mirror ([1,0,0])make_rodholder();
        mirror ([0,1,0])make_rodholder();
        mirror ([1,0,0])mirror ([0,1,0])make_rodholder();
        main_body();
    }
}

module make_rodholder(){
    translate([7*length_x/16,Rail_Spacing/2,Rail_Diameter*.51 + Height_z])//translate to get rail holder to 0z
    difference(){
    translate([0,0,Rail_Diameter*-.09])cube([length_x/8,Rail_Diameter*1.5,Rail_Diameter*.82],true);//0.82 rail diameter gives limited contact with incircle; -0.09 translate sets floor
    rotate ([0,90,0]) make_hex(-30, 30, 90, Rail_Diameter, length_x/8 );
    }

}
module make_holes(Hole_Diameter){
    if (Number_of_Holes > 0)
        {
            for (a=[1:Number_of_Holes])
            translate ([(a * length_x/ (Number_of_Holes +1)) - (length_x/2),0,0]) make_hex(-30, 30, 90, Hole_Diameter, 2*Height_z);
    }
}
module make_hex(Rx,Ry,Rz,Diam,Len){
    s =Diam/2 * ( 2 * tan(30));
        for (r = [Rx,Ry,Rz]) rotate([0,0,r]) cube([s, Diam, Len], true);
            }
module main_body(){
    translate ([0,0,(Height_z ) /2]) cube(size = [length_x, Width_y, (Height_z )], center = true);
}
module fancy_body(){
hull(){
    translate ([0,0,Height_z/4]) cube (size = [length_x,Width_y,Height_z/2], center = true);
    translate ([0,0,Height_z/2]) scale ([length_x,2,1])rotate ([0,90,0]) cylinder (h = 1, r=Height_z/2, center = true, $fn=100);
}
}

```


[User]
I'm looking to design a star dial, also known as a nocturnal, in OpenSCAD. It's a tool used for telling time using stars in the night sky. I've seen some examples and have some ideas about how it should function, but I'd like you to create the OpenSCAD code for me.

Here's a breakdown of the parts and the parameters I'd like to be able to control:

**Overall Structure:**

The dial will have several main parts: an outer ring, an inner ring, a pointer, and a handle. I need to be able to print each of these separately so please design with this in mind.

**Outer Ring:**

*   **Radius:** This is the overall size of the dial. Let's start with a parameter named `radius` set to 35, but I'd like it to be customizable.
*   **Design Style:** The outer ring's face should be able to display either a "Fill", "Spiral", or "Straight" pattern. This parameter should be called `style` and default to "Spiral".
    *   "Fill" would be a solid filled in cylinder.
    *   "Spiral" would have a spiral design cut into it. I'd like to also have a `density` parameter, defaulting to 5,  to control how dense the spiral is.
    *   "Straight" would have a series of parallel lines cut into it, with the same density parameter as the spiral.
*   **Month Markings:** The outer ring needs to display the months of the year. I want to choose between different notations:
    *   A parameter `month_notation` that is 2 will show 3-letter abbreviations (e.g., "Jan", "Feb", "Mar").
    *   Setting `month_notation` to 3 will show 1-letter abbreviations (e.g., "J", "F", "M").
    *  I will also want to be able to modify the font used here, I'd like a parameter `font_choice`, defaulting to "Russo One". All google fonts should be useable.
*   The outer ring should have small marks or notches for each day of the year, like a calendar.

**Inner Ring:**

*   The inner ring will sit inside the outer ring and will also need a design style and density parameter like the outer ring
*   **Time Markings:** This ring needs to show the hours of the day, using either Roman numerals or Arabic numerals:
    *   A parameter `time_notation` which is 1 will use Roman numerals (I, II, III, etc.).
    *   Setting it to 2 will use Arabic numerals (1, 2, 3, etc.).
    *   Like the outer ring, font choice is important, and will follow the `font_choice` parameter.
*   **Constellation Markers:** There should be markers to represent reference stars/constellations to use for alignment:
    *   The pointer stars of Ursa Major
    *   Kochab of Ursa Minor
    *   Shedar of Cassiopeia
    *   For simplicity, just small star-shaped markers for the constellations will work.

**Pointer:**

*   The pointer will need to be able to rotate around the center.
*   It should have a sight for the reference stars.

**Handle:**

*   The handle should have a hole in the middle to sight through to polaris, and should have its own style parameter similar to the inner and outer rings.
*   It should be designed to be printed separately and assembled after printing.

**General:**

*   I will need a parameter to determine the size of the stars, named `star_size` and defaulting to 0.5.
*   I'm using a value of `delta = 0.001` to make sure that there are no touching faces. I'm not sure how this works, but I'd like to keep this parameter available for potential changes.
*   I want to keep this whole design to be fully parametric, and I'd like to avoid using libraries where possible.

Could you generate the OpenSCAD code for this? Let me know if you need anything clarified.

[Assistant]
Star_Dial.scad:
```
// preview[view:west, tilt:top]

//Which part would you like to render? (Parts must be printed separately).
part="All"; //[All, Outer Ring, Inner Ring, Pointer, Handle]
//Design of the faces.
style="Spiral"; //[Fill, Spiral, Straight]
//Density of the design.
density=5; //[1:10]
month_notation=2; //[2:3-letter, 3:1-letter]
time_notation=1; //[1:Roman numerals, 2:Arabic numerals]
//Customizer currently supports all google fonts (google.com/fonts).
font_choice="Russo One";

/*[Hidden]*/
//Radius of the outer ring (ie. the whole star dial).
radius=35;
//Diameter of small stars, radius of pointer stars.
star_size=0.5;
//Removes touching faces
delta = 0.001;

month_data=[
[0, "", "", "", 0, 0],
[1, "January", "Jan", "J", 31, 31],
[2, "February", "Feb", "F", 28, 59],
[3, "March", "Mar", "M", 31, 90],
[4, "April", "Apr", "A", 30, 120],
[5, "May", "May", "M", 31, 151],
[6, "June", "Jun", "J", 30, 181],
[7, "July", "Jul", "J", 31, 212],
[8, "August", "Aug", "A", 31, 243],
[9, "September", "Sep", "S", 30, 273],
[10, "October", "Oct", "O", 31, 304],
[11, "November", "Nov", "N", 30, 334],
[12, "December", "Dec", "D", 31, 365],
];

time=[
[0, "XII", "12"],
[1, "I", "1"],
[2, "II", "2"],
[3, "III", "3"],
[4, "IV", "4"],
[5, "V", "5"],
[6, "VI", "6"],
[7, "VII", "7"],
[8, "VIII", "8"],
[9, "IX", "9"],
[10, "X", "10"],
[11, "XI", "11"],
[12, "XII", "12"],
[13, "I", "1"],
[14, "II", "2"],
[15, "III", "3"],
[16, "IV", "4"],
[17, "V", "5"],
[18, "VI", "6"],
[19, "VII", "7"],
[20, "VIII", "8"],
[21, "IX", "9"],
[22, "X", "10"],
[23, "XI", "11"]
];

module outer_ring(radius, month_notation){
    translate([0, 0, -3])
    intersection(){
        difference(){
            cylinder(r=(2*(radius/3)), h=((PI*(radius-5))/365)+3, $fn=365);

            translate([0,0,-delta])
            cylinder(r=6.5, h=((PI*(radius-5))/365)+3+2*delta, $fn=36);
        }
        if(style=="Fill"){
        }
        if(style=="Spiral"){
            for(i=[0:180/density:360]){
                rotate(a=i, v=[0, 0, 1])
                translate([radius/2, 0, -delta])
                difference(){
                    cylinder(r=radius/2, h=((PI*(radius-5))/365)+3+2*delta, $fn=365);

                    cylinder(r=(radius/2)-2, h=((PI*(radius-5))/365)+3+2*delta, $fn=365);
                    translate([-radius, 0, 0])
                    cube([2*radius, radius, ((PI*(radius-5))/365)+3+2*delta]);
                }
            }
        }
        if(style=="Straight"){
            for(i=[0:180/density:360]){
                rotate(a=i, v=[0, 0, 1])
                translate([6, -1, 0])
                cube([2*(radius/3)-6, 2, ((PI*(radius-5))/365)+3]);
            }
        }
    }
    for (i=[0:365], l=[0:4]){
        rotate(a=(i*5*360/365)+(l*360/365), v=[0, 0, 1]){
            rotate(a=90, v=[0, 1, 0])
            translate([0, 0, radius-5])
            cylinder(d=((2*PI*(radius-5))/365), h=l+1, $fn=4);

            translate([radius-5, -((PI*(radius-5))/365), -1])
            cube([l+1, ((2*PI*(radius-5))/365), 1]);
        }
    }
    difference(){
        union(){
            translate([0, 0, -3])
            cylinder(r=radius, h=2, $fn=365);

            translate([0, 0, -1])
            cylinder(r=radius-5, h=((PI*(radius-5))/365)+1, $fn=365);
        }
        rotate(a=-90, v=[0, 1, 0])
        linear_extrude(h=radius)
        polygon(points=[[-2, -2], [-2, 2], [-4, 0]]);

        translate([0, 0, -3-delta])
        cylinder(r=2*radius/3, h=((PI*(radius-5))/365)+3+2*delta, $fn=365);

        for(month=[1:12]){
            for (i=[month_data[month][5]]){
                rotate(a=(i*360/365)-(180/365), v=[0, 0, 1])
                rotate(a=90, v=[0, 1, 0])
                translate([-((PI*(radius-5))/365), 0, radius/2])
                cylinder(d=((2*PI*(radius-5))/365), h=(radius/2)-5, $fn=4);
            }
            for (i=[month_data[month][5]]){
                rotate(a=(i*360/365)-(180/365)-((month_data[month][4])/2), v=[0, 0, 1])
                translate([3*(radius/4), 0, -1])
                rotate(a=-90, v=[0, 0, 1])
                linear_extrude(h=1)
                text(month_data[month][month_notation], font=str(font_choice), size=radius/10, valign="center", halign="center");
            }
        }
    }
    translate([0, 0, -3])
    difference(){
        cylinder(r=6.5, h=((PI*(radius-5))/365)+3, $fn=36);

        translate([0,0,-delta])
        cylinder(r=5.5, h=1+delta, $fn=36);

        cylinder(r=4.5, h=((PI*(radius-5))/365)+3+delta, $fn=36);
    }
}
module inner_ring(radius){
    intersection(){
        difference(){
            cylinder(r=(2*(radius/3))-(radius/6), h=2, $fn=36);

            translate([0,0,-delta])
            cylinder(r=6.5, h=2+2*delta, $fn=36);
        }
        if(style=="Fill"){
        }
        if(style=="Spiral"){
            for(i=[0:180/density:360]){
                rotate(a=i, v=[0, 0, 1])
                translate([radius/2, 0, 0])
                difference(){
                    cylinder(r=radius/2, h=2, $fn=36);

                    translate([0,0,-delta])
                    cylinder(r=(radius/2)-2, h=2+2*delta, $fn=36);

                    translate([-radius, 0, -delta])
                    cube([2*radius, radius, 2+2*delta]);
                }
            }
        }
        if(style=="Straight"){
            for(i=[0:180/density:360]){
                rotate(a=i, v=[0, 0, 1])
                translate([6, -1, 0])
                cube([radius/3, 2, 2]);
            }
        }
    }
    difference(){
        for(i=[0:23]){
            rotate(a=15*(time[i][0]), v=[0, 0, 1])
            translate([(2*(radius/3))-(radius/10), 0, 0])
            cylinder(r=radius/10, h=2, $fn=36);
        }
        for(i=[0, 1, 2, 3, 4, 5, 6, 7, 8, 16, 17, 18, 19 ,20, 21, 22, 23]){
            rotate(a=15*(time[i][0]), v=[0, 0, 1])
            translate([(2*(radius/3))-(radius/10), 0, 1])
            rotate(a=-90, v=[0, 0, 1])
            linear_extrude(h=1)
            text(time[i][time_notation], font=str(font_choice), size=radius/20, valign="center", halign="center");
        }
    }
    difference(){
        union(){
            for (i=[65, 121.5, -90.5]){
                rotate(a=i, v=[0, 0, 1]){
                    translate([radius-5, 0, 0])
                    cylinder(r=5, h=2, $fn=36);

                    translate([2*(radius/3)-2, 0, 0])
                    cube([(radius/3)-3, 5, 2]);
                }
            }
            cylinder(r=6.5, h=2, $fn=36);
        }
        union(){
            for (i=[65, 121.5, -90.5]){
                rotate(a=i, v=[0, 0, 1])
                translate([radius-10, -5, -delta])
                cube([10, 5, 2+2*delta]);
            }
            rotate(a=65, v=[0, 0, 1])
            translate([radius-9, 1.5, 2])
            ursa_major(star_size);

            rotate(a=121.5, v=[0, 0, 1])
            translate([radius-9, 1.5, 2])
            ursa_minor(star_size);

            rotate(a=-90.5, v=[0, 0, 1])
            translate([radius-9, 1, 2])
            cassiopeia(star_size);

            translate([0,0,-delta])
            cylinder(r=4.5, h=2+2*delta, $fn=36);
        }
    }
}
module pointer(radius){
    difference(){
        union(){
            rotate_extrude($fn=36){
                translate([-5, 0.5, 0])
                circle(d=1, $fn=36);

                translate([-5, 0, 0])
                square(1);
            }
            cylinder(r=4.5, h=((PI*(radius-5))/365)+6, $fn=36);

            translate([0, 0, ((PI*(radius-5))/365)+4])
            cube([4.5, radius, 2]);

            translate([0, radius, ((PI*(radius-5))/365)+4])
            cylinder(r=4.5, h=2, $fn=36);
        }
        union(){
            translate([0,0,-delta])
            cylinder(r=2.5, h=((PI*(radius-5))/365)+6+2*delta, $fn=36);

            for(i=[0:1]){
                rotate(a=i*90, v=[0, 0, 1]){
                    translate([-5.5, 0, 3])
                    rotate(a=90, v=[0, 1, 0])
                    cylinder(r=2, h=11, $fn=36);

                    translate([-5.5, -1.5, -delta])
                    cube([11, 3, 3+delta]);
                }
            }
            translate([-4.5, radius-4.5, ((PI*(radius-5))/365)+4-delta])
            cube([4.5, 9, 2+2*delta]);
        }
    }
}
module handle(radius){
    linear_extrude(height=radius/3)
    polygon(points=[[-2, -2], [-2, 2], [-3, 1], [-3, -1]]);

    difference(){
        union(){
            translate([-3, 0, 5])
            cylinder(r=5, h=(radius/3)-3, $fn=36);

            translate([-3, 0, 5])
            sphere(r=5, $fn=36);

            difference(){
                translate([-3, 0, 1.5*radius])
                sphere(r=5, $fn=36);

                translate([-8, -5, (1.5*radius)-5])
                cube([10, 10, 5]);
            }
            if(style=="Fill"){
                translate([-3, 0, (radius/3)+2])
                cylinder(r=5, h=(1.5*radius)-(radius/3)-2, $fn=36);
            }
            if(style=="Spiral"){
                translate([-3, 0, (radius/3)+2])
                for(i=[0:360/density:360]){
                    rotate(a=i, v=[0, 0, 1])
                    linear_extrude(height=(1.5*radius)-(radius/3)-2, twist = 360)
                    translate([4, 0, 0])
                    circle(r=1, $fn=36);
                }
            }
            if(style=="Straight"){
                translate([-3, 0, (radius/3)+2])
                for(i=[0:360/density:360]){
                    rotate(a=i, v=[0, 0, 1])
                    translate([4, 0, 0])
                    cylinder(r=1, h=(1.5*radius)-(radius/3)-2, $fn=36);
                }
            }
        }
        translate([-3, -5, -delta])
        cube([5, 10, radius/3+delta]);
    }
}
module cassiopeia(star_size){
    translate([0, 3.8*star_size, 0])
    sphere(d=star_size, $fn=36);

    translate([3*star_size, 1.2*star_size, 0])
    sphere(d=star_size, $fn=36);

    translate([5.6*star_size, 2.2*star_size, 0])
    sphere(d=star_size, $fn=36);

    translate([7.9*star_size, 0, 0])
    sphere(d=1.5*star_size, $fn=36);

    translate([10*star_size, 2.8*star_size, 0])
    sphere(d=star_size, $fn=36);
}
module ursa_major(star_size){
    translate([0, 2*star_size, 0])
    sphere(d=star_size, $fn=36);

    translate([2.5*star_size, 2.6*star_size, 0])
    sphere(d=star_size, $fn=36);

    translate([6.2*star_size, 1.5*star_size, 0])
    sphere(d=star_size, $fn=36);

    translate([6.9*star_size, 0, 0])
    sphere(d=star_size, $fn=36);

    translate([9.6*star_size, 0.3*star_size, 0])
    sphere(d=star_size, $fn=36);

    translate([9.7*star_size, 2.3*star_size, 0])
    sphere(d=1.5*star_size, $fn=36);
}
module ursa_minor(star_size){
    translate([0, 1.2*star_size, 0])
    sphere(d=star_size, $fn=36);

    translate([2.4*star_size, 0.3*star_size, 0])
    sphere(d=star_size, $fn=36);

    translate([5.2*star_size, 0, 0])
    sphere(d=star_size, $fn=36);

    translate([7.6*star_size, 0.9*star_size, 0])
    sphere(d=star_size, $fn=36);

    translate([9.5*star_size, 0, 0])
    sphere(d=star_size, $fn=36);

    translate([9.6*star_size, 3.3*star_size, 0])
    sphere(d=1.5*star_size, $fn=36);

    translate([10.8*star_size, 1.6*star_size, 0])
    sphere(d=star_size, $fn=36);
}

module render_part(part){
    if(part=="All"){
        translate([-(2*(radius/3)), 0, -((PI*(radius-5))/365)])
        rotate(a=-90, v=[0, 1, 0])
        handle(radius);

        translate([0, 0, -((PI*(radius-5))/365)])
        outer_ring(radius, month_notation, font_choice);

        inner_ring(radius);
        translate([0, 0, -3])
        pointer(radius);
    }
    else if(part=="Outer Ring"){
        translate([0, 0, -((PI*(radius-5))/365)])
        outer_ring(radius, month_notation, font_choice);
    }
    else if(part=="Inner Ring"){
        inner_ring(radius);
    }
    else if(part=="Pointer"){
        translate([0, 0, -3])
        pointer(radius);
    }
    else if(part=="Handle"){
        translate([-(2*(radius/3)), 0, -((PI*(radius-5))/365)])
        rotate(a=-90, v=[0, 1, 0])
        handle(radius);
    }
}
render_part(part);

```


[User]
Okay, I'm looking for a parametric OpenSCAD design for a mesh vase, kind of like a hyperbolic structure made of straight beams. I've seen a design before, but it's deprecated and has too many settings that I don't really need. I want to be able to choose the overall style - either a "basket4" or "basket6" pattern, which determines how the beams intersect. "Basket4" will make it look like the beams are creating squares, and "basket6" will make it look like they create triangles when they intersect.

I need to be able to control the radius at the top and bottom of the vase, the overall height, the density of the beams (which is how many there are), and the size of each individual beam (I'd like this to be a radius).

The density should ideally be a multiple of 4 for the "basket4" design and a multiple of 6 for the "basket6" design to make sure the segments are arranged nicely. I’m not sure how to calculate the length of the beam based on all this so you'll have to figure that out.

So I'm thinking 5 parameters, `mode`, `radius`, `height`, `density`, and `segment_size`. I would like to be able to set the mode to either "basket4" or "basket6". I'd like to specify the radius of the top and bottom of the vase. I’d like the height to be in the z direction, and then the density should indicate how many beams should be along the perimeter. And segment_size should be the radius of the cylindrical beams. I am not using any libraries.

[Assistant]
meshvase.scad:
```
// LIB
TAU = 360; //2.0 * PI;
function r2d(a) = 180 * a / PI;

// choose the frequency that basket segments form a complete revolution. Effects inner radius.
mode = "basket6"; //[basket4, basket6]

// top and bottom radius
radius = 5.0; //[0.1:0.01:100.0]

// height
height = 5.0; //[0.1:0.01:100.0]

// density of segments (use multiples of 4 for basket4 use multiples of 6 for basket6
density = 48; //[4:2:100]

// segment radius
segment_size = 0.1; //[0.05:0.01:10.0]

if (mode == "basket4"){
    basket4(radius,height,density,segment_size);
} else if (mode == "basket6"){
    basket6(radius,height,density,segment_size);
}

module basket4(radius = 5.0, height = 5.0, numSticks = 48.0, stickWidth = 0.1){

    chordLength = sqrt((radius*radius) + (radius*radius));
    length = sqrt((chordLength*chordLength)  +(height*height));
    angleY = atan2(chordLength, height);
    angleZ = atan2(radius, radius);

    for( i = [0:numSticks]){
        dir = i%2 ? -1 : 1;
        startPos = i%2 ? i : i-1;
        ratio = TAU/numSticks;
        position = startPos * ratio;
        translate([radius * cos(position),radius * sin(position), 0]){
           rotate([0, 0,dir * angleZ]){
                rotate([0,0,position]){
                    rotate([0,-angleY,0]){
                        cylinder(length, r=stickWidth, $fn = 20);
                    }
                }
            }
        }
    }
}

module basket6(radius = 5.0, height = 5.0, numSticks = 48.0, stickWidth = 0.1){

    r_sq = radius * radius;
    // law of cosines
    chordLength = sqrt((r_sq + r_sq) - (2 * r_sq * cos(TAU / 3)));
    length = sqrt((chordLength*chordLength) + (height*height));

    angleY = atan2(chordLength, height);
    angleZ = 30;

    for( i = [0:numSticks]){
        dir = i%2 ? -1 : 1;
        startPos = i%2 ? i : i-1;
        ratio = TAU/numSticks;
        position = startPos * ratio;
        translate([radius * cos(position),radius * sin(position), 0]){
           rotate([0, 0,dir * angleZ]){
                rotate([0,0,position]){
                    rotate([0,-angleY,0]){
                        cylinder(length, r=stickWidth, $fn = 20);
                    }
                }
            }
        }
    }
}

```