[User]
I'd like a customizable sports trophy generator. I need to be able to specify the text for three lines, a main line, and then an upper and lower line.  Each line needs its own font selection, so that needs to be customizable too.

For icons, I need to be able to place them on the left and right of both the upper and lower lines of text.  I want to be able to choose from a variety of icons, like a simple ball, basketball, baseball, football, soccer ball, a star, a hockey stick, and maybe mirrored version of the hockey stick, and crossed hockey sticks. It'd be great to have a golf club, and a mirrored golf club, too. Oh, and some karate icons would be awesome. I'm thinking like, a karate kick, a few different poses, some nunchucks, and a karate belt and mirrored karate belt. I'd also like some book icons as well, maybe six different book icons. I need to be able to select which icon goes into each of the four icon positions.

The trophy should have a main circle with a bevel. The angle of the bevel and its height should be customizable. I also need to control the thickness of the circle, the thickness of the lines making up the icons, and the radius of the circle, as well as the height of the entire trophy.

The base should be a rounded cube, also with customizable corner radius and the amount it sticks out past the main circle. It also needs to have up to five customizable text lines on the bottom of the base, each with its own font selection. So that’s text and font selection for each of those five lines.

It needs to work with the OpenSCAD customizer. I'm not using any libraries, so I don't need those specified.

[Assistant]
Sport_Trophy_V6.scad:
```
///////////////////////////////////////////////////////////////////////////////
// Sport Trophy
//
// OpenSCAD file that creates a sports trophy with appropriate text and icons.
// The trophy is compatible with the OpenSCAD customizer.  It consists of 3
// lines of text.  The first and third lines can also contain sport icons.
//  Included icons are:
//      - Simple ball
//      - Basketball
//      - Baseball
//      - U.S. Football
//      - Soccer ball
//      - Star
//      - Hockey Stick
//      - Mirrored Hockey Stick
//      - Crossed Hockey Sticks
//      - Golf Club and Ball
//      - Mirrored Golf Club and Ball
//      - Several karate poses and icons
//      - Several book icons
//
// These should be easily extensible.  Text, font, and icon placement are
// customizable as well as size of trophy and related measurements.
//
// History:
//   27-APR-2024 (V6)
//   Added book icons and other minor cleanup.
//   16-MAY-2023 (V5)
//   Added karate icons and base bottom text lines.  Slightly changed alignment
//   of text and icon fields.
//   15-APR-2023 JMC
//   Added hockey and golf icons.
//
// Author: J.M.Corbett 21-March-2023
///////////////////////////////////////////////////////////////////////////////

/* [Main Text Parameters] */
SuperStarName = "THOMAS";                       // Main/central string.
UpperText     = "BLACKBELT";                    // Upper string.
LowerText     = "TAEKWONDO";                    // Lower string.
MainFont      = "Gallery Wide:style=Normal";    // Font for main string.
UpperFont     = "LatinComD:style=Regular";      // Font for upper string.
LowerFont     = "LatinComD:style=Regular";      // Font for lower string.

/* [Icon Placement Parameters] */
UpperLeftIcon  = 17;    // [0:Empty, 1:Ball, 2:Basketball, 3:Baseball, 4:Football, 5:Soccerball, 6:Star, 7:Hockey Stick, 8:Hockey Stick 2, 9:Hockey Sticks, 10:Golf Club, 11:Golf Club 2, 12: Karate Kick 1, 13: Karate Kick 2, 14: Karate Kick 3, 15: Karate Pose, 16: Nunchucks, 17: Karate Belt, 18: Karate Belt Mirror, 19: Book 1, 20: Book 2, 21: Book 3, 22: Book 4, 23: Book 5, 24: Book 6]
UpperRightIcon = 18;    // [0:Empty, 1:Ball, 2:Basketball, 3:Baseball, 4:Football, 5:Soccerball, 6:Star, 7:Hockey Stick, 8:Hockey Stick 2, 9:Hockey Sticks, 10:Golf Club, 11:Golf Club 2, 12: Karate Kick 1, 13: Karate Kick 2, 14: Karate Kick 3, 15: Karate Pose, 16: Nunchucks, 17: Karate Belt, 18: Karate Belt Mirror, 19: Book 1, 20: Book 2, 21: Book 3, 22: Book 4, 23: Book 5, 24: Book 6]
LowerLeftIcon  = 14;    // [0:Empty, 1:Ball, 2:Basketball, 3:Baseball, 4:Football, 5:Soccerball, 6:Star, 7:Hockey Stick, 8:Hockey Stick 2, 9:Hockey Sticks, 10:Golf Club, 11:Golf Club 2, 12: Karate Kick 1, 13: Karate Kick 2, 14: Karate Kick 3, 15: Karate Pose, 16: Nunchucks, 17: Karate Belt, 18: Karate Belt Mirror, 19: Book 1, 20: Book 2, 21: Book 3, 22: Book 4, 23: Book 5, 24: Book 6]
LowerRightIcon = 13;    // [0:Empty, 1:Ball, 2:Basketball, 3:Baseball, 4:Football, 5:Soccerball, 6:Star, 7:Hockey Stick, 8:Hockey Stick 2, 9:Hockey Sticks, 10:Golf Club, 11:Golf Club 2, 12: Karate Kick 1, 13: Karate Kick 2, 14: Karate Kick 3, 15: Karate Pose, 16: Nunchucks, 17: Karate Belt, 18: Karate Belt Mirror, 19: Book 1, 20: Book 2, 21: Book 3, 22: Book 4, 23: Book 5, 24: Book 6]

/* [Base Bottom Text Parameters] */
BottomFont1 = "LatinComD:style=Regular";        // Font for bottom line 1.
BottomLine1 = "UP TO 5";                        // Text for bottom line 1.
BottomFont2 = "LatinComD:style=Regular";        // Font for bottom line 2.
BottomLine2 = "LINES OF TEXT";                  // Text for bottom line 2.
BottomFont3 = "LatinComD:style=Regular";        // Font for bottom line 3.
BottomLine3 = "MAY BE ENGRAVED";                // Text for bottom line 3.
BottomFont4 = "LatinComD:style=Regular";        // Font for bottom line 4.
BottomLine4 = "ON THE BOTTOM";                  // Text for bottom line 4.
BottomFont5 = "LatinComD:style=Regular";        // Font for bottom line 5.
BottomLine5 = "OF THE BASE";                    // Text for bottom line 5.

/* [Dimensional Parameters] */
// Main/enclosing circle radius.
MainRadius       = 50;  // [25:150]
// Thickness or main circle.
MainThickness    = 1;   // [.5:.5:5]
// Angle to bevel main circle and all text.
BevalAngle       = 35;  // [0:1:60]
// Height above base to start bevel (can be nagative).
BevelHeight      = -3;  // [-100:.2:100]
// Thickness of thing lines.
ThingThickness   = 1;   // [.5:.5:10]
// Height of square base.
BaseHeight       = 8;   // [0:.2:20]
// Radius to round base corners.
BaseCornerRadius = 3;   // [0:.5:10]
// Amount to extend base beyond main circle.
BaseOverhang     = 5;   // [0:.5:25]

module dummy() {}

// Constants - hidden from the customizer.
$fn = 120;
txtHeight = MainRadius / 6;   // Allows for nice vertical spacing between text lines.
charWidth = MainRadius / 13;  // Should be able to display 26 chars per line max.
engraveHeight = 0.8;          // Height of bottom engraved letters.

// Icon selection values.
NO_ICON               = 0;
BALL                  = 1;
BASKETBALL            = 2;
BASEBALL              = 3;
FOOTBALL              = 4;
SOCCERBALL            = 5;
STAR                  = 6;
HOCKEY_STICK          = 7;
HOCKEY_STICK_MIRROR   = 8;
CROSSED_HOCKEY_STICKS = 9;
GOLF_CLUB             = 10;
GOLF_CLUB_MIRROR      = 11;
KARATE_KICK_1         = 12;
KARATE_KICK_2         = 13;
KARATE_KICK_3         = 14;
KARATE_POSE_1         = 15;
KARATE_NUNCHUCK_1     = 16;
KARATE_BELT           = 17;
KARATE_BELT_MIRROR    = 18;
BOOK_1                = 19;
BOOK_2                = 20;
BOOK_3                = 21;
BOOK_4                = 22;
BOOK_5                = 23;
BOOK_6                = 24;

// Height (shouldn't need to change this.)
mainH = 4 * MainRadius;

///////////////////////////////////////////////////////////////////////////////
// PlaceThing()
//
// Places an icon with a specified size in a specified location.
//
// ARGUMENTS:
//   - thing - specifies the icon to be placed as follows:
//     - 0  = Empty (no icon)
//     - 1  = Simple ball
//     - 2  = Basketball
//     - 3  = Baseball
//     - 4  = U.S. football
//     - 5  = Soccer ball
//     - 6  = Star
//     - 7  = Hockey stick
//     - 8  = Hockey stick (mirror)
//     - 9  = Hockey sticks crossed
//     - 10 = Golf club
//     - 11 = Golf club (mirror)
//     - 12 = Karate kick 1
//     - 13 = Karate kick 2
//     - 14 = Karate kick 3
//     - 15 = Karate pose
//     - 16 = Karate nunchucks
//     - 17 = Karate belt
//     - 18 = Karate belt (mirror)
//     - 19 = Book 1
//     - 20 = Book 2
//     - 21 = Book 3
//     - 22 = Book 4
//     - 23 = Book 5
//     - 24 = Book 6
//
//     To add more, simply add to the list of module calls within the translate
//     scope.
//   - rad - specifies the radius of the object
//   - thick - specifies the thickness of the lines outlining the object.
//             Note that not all objectes need this argument.
//   - x - specifies the X offset to place the object.
//   - y - specifies the Y offset to place the object.
///////////////////////////////////////////////////////////////////////////////
module PlaceThing(thing, rad, thick, x, y)
{
    translate([x, y]) SelectThing(thing)
    {
        dummy();
        Ball(rad, thick);
        Basketball(rad, thick);
        Baseball(rad, thick);
        Football(rad, thick);
        SoccerBall(rad, thick);
        Star(r1 = .4 * rad, r2 = rad);
        HockeyStick(rad, thick);
        mirror([1, 0, 0]) HockeyStick(rad, thick);
        resize([rad * 1.3, rad * 1.3]) union()
        {
            HockeyStick(10, 1);
            mirror([1, 0, 0]) HockeyStick(10, 1);
        }
        scale([1.2, 1.2]) GolfClubAndBall(rad, thick);
        scale([1.2, 1.2]) mirror([1, 0, 0]) GolfClubAndBall(rad, thick);
        Karate(thing, rad);
        Karate(thing, rad);
        Karate(thing, rad);
        Karate(thing, rad);
        Karate(thing, rad);
        Karate(thing, rad);
        mirror([1, 0, 0]) Karate(thing, rad);
        Books(thing, rad);
        Books(thing, rad);
        Books(thing, rad);
        Books(thing, rad);
        Books(thing, rad);
        Books(thing, rad);
    }
} // End PlaceThing().

///////////////////////////////////////////////////////////////////////////////
// SelectThing()
//
// Usees the OpenSCAD children() command to select a thing to place.
//
// ARGUMENTS:
//   - thing - specifies the icon to be placed.
///////////////////////////////////////////////////////////////////////////////
module SelectThing(thing)
{
    children(thing);
} // End SelectThing().

///////////////////////////////////////////////////////////////////////////////
// Trophy()
//
// Creates the entire trophy.
///////////////////////////////////////////////////////////////////////////////
module Trophy()
{
    // Use difference() to create the bevel.
    color("gold") difference()
    {
        // Extrude the 2d elements.
        linear_extrude(mainH, convexity = 10)
        {
            // Create the main enclosing circle.
            Ball(MainRadius, MainThickness);

            // Add the main text.
            resize([1.7 * MainRadius, .5 * MainRadius])
                text(SuperStarName, font = MainFont,
                    size = 14, halign = "center", valign = "center");

            // Add the upper text.
            translate([0, MainRadius * .37]) resize([MainRadius * .75, MainRadius * .22])
                text(UpperText, font = UpperFont, size = 10,
                    halign = "center");

            // Add the lower text.
            translate([0, -MainRadius * .6]) resize([MainRadius * .75, MainRadius * .22])
                text(LowerText, font = LowerFont, size = 10,
                    halign = "center");

            // Add the icons as specified.
            PlaceThing(UpperLeftIcon, MainRadius * .15, ThingThickness,
                       -MainRadius * .6, MainRadius *.48);
            PlaceThing(UpperRightIcon, MainRadius * .15, ThingThickness,
                       MainRadius * .6, MainRadius *.48);
            PlaceThing(LowerLeftIcon, MainRadius * .15, ThingThickness,
                       -MainRadius * .6, -MainRadius * .48);
            PlaceThing(LowerRightIcon, MainRadius * .15, ThingThickness,
                       MainRadius * .6, -MainRadius * .48);
        }
        // Use a cube to remove beveled part.
        translate([-MainRadius * 2, -MainRadius, BevelHeight - .01]) rotate([BevalAngle, 0, 0])
            cube(5 * MainRadius);
    }

    // Add the base with up to 5 lines of text.
    difference()
    {
        // Create the base.
        color("black") translate([0, 0, -BaseHeight / 2])
            RoundedCube(
                [2 * (MainRadius + BaseOverhang), 2 * (MainRadius + BaseOverhang), BaseHeight],
                radius = BaseCornerRadius, center = true);

        // Carve out the 5 lines of text.
        color("white")
        {
            translate([0, -1.5 * MainRadius * .3, -BaseHeight - .1])
            linear_extrude(height = engraveHeight, center = false)
            mirror([0, 1])
            union()
            {
                translate([-len(BottomLine1) * charWidth / 2, 0])
                    resize([len(BottomLine1) * charWidth, txtHeight, 0])
                    text(BottomLine1, font = BottomFont1, size = 10);

                translate([-len(BottomLine2) * charWidth / 2, -MainRadius * .25])
                    resize([len(BottomLine2) * charWidth, txtHeight, 0])
                    text(BottomLine2, font = BottomFont2, size = 10);

                translate([-len(BottomLine3) * charWidth / 2, -2 * MainRadius * .25])
                    resize([len(BottomLine3) * charWidth, txtHeight, 0])
                    text(BottomLine3, font = BottomFont3, size = 10);

                translate([-len(BottomLine4) * charWidth / 2, -3 * MainRadius * .25])
                    resize([len(BottomLine4) * charWidth, txtHeight, 0])
                    text(BottomLine4, font = BottomFont4, size = 10);

                translate([-len(BottomLine5) * charWidth / 2, -4 *MainRadius * .25])
                    resize([len(BottomLine5) * charWidth, txtHeight, 0])
                    text(BottomLine5, font = BottomFont5, size = 10);
            }
        }
    }
} // End Trophy().

module Star(rad)
{
    resize([2 * rad, 0], auto = true) polygon(shape_pentagram(7));
}

///////////////////////////////////////////////////////////////////////////////
// Ball()
//
// Simple ball.
//
// ARGUMENTS:
//   - rad   = specifies the radius.
//   - thick = specifies the thickness of the outline.
///////////////////////////////////////////////////////////////////////////////
module Ball(rad, thick)
{
    // Create the outline of the ball.
    difference()
    {
        circle(r = rad);
        circle(r = rad - thick);
    }
} // End Ball().

///////////////////////////////////////////////////////////////////////////////
// Basketball()
//
// Basketball.
//
// ARGUMENTS:
//   - rad   = specifies the radius.
//   - thick = specifies the thickness of the outline.
///////////////////////////////////////////////////////////////////////////////
module Basketball(rad, thick)
{
    intersection()
    {
        union()
        {
            // Create outline and curved lines.
            Baseball(rad, thick);

            // Add straight lines to look like a basketball.
            translate([0, -rad]) square([thick, 2 * rad]);
            translate([rad / 3, 0]) square([rad, thick]);
            translate([-rad - rad / 3, 0]) square([rad, thick]);
        }
        // Trimm off anything outside the ball.
        circle(rad);
    }
} // End Basketball().

///////////////////////////////////////////////////////////////////////////////
// Baseball()
//
// Baseball.
//
// ARGUMENTS:
//   - rad   = specifies the radius.
//   - thick = specifies the thickness of the outline.
///////////////////////////////////////////////////////////////////////////////
module Baseball(rad, thick)
{
    intersection()
    {
        union()
        {
            // Create outline and curved lines.
            Ball(rad, thick);
            translate([-rad - rad * 1 / 3, 0]) Ball(rad, thick);
            translate([rad + rad * 1 / 3, 0]) Ball(rad, thick);
        }
        // Trimm off anything outside the ball.
        circle(rad);
    }
} // End Baseball().

///////////////////////////////////////////////////////////////////////////////
// Football()
//
// Football.
//
// ARGUMENTS:
//   - rad   = specifies the radius.
//   - thick = specifies the thickness of the outline.
///////////////////////////////////////////////////////////////////////////////
module Football(rad, thick)
{
    intersection()
    {
        union()
        {
            // Create the outline of the football.
            scale([1, .5]) Ball(rad, thick);

            // Create the center line.
            square([2 * rad - thick, thick / 2], center = true);

            // Create the threads.
            translate([thick * 2, 0,]) square([thick, 3 * thick], center = true);
            translate([-thick * 2, 0,]) square([thick, 3 * thick], center = true);
            translate([0, 0,]) square([thick, 3 * thick], center = true);

            // Create the two end markers.
            translate([-rad * .6, 0]) square([thick * 1.5, rad], center = true);
            translate([rad * .6, 0]) square([thick * 1.5, rad], center = true);
        }
        // Trimm off anything outside the ball.
        scale([1, .5]) circle(r = rad);
    }
} // End Football().

///////////////////////////////////////////////////////////////////////////////
// SoccerBall()
//
// Soccer ball.
//
// ARGUMENTS:
//   - rad   = specifies the radius.
//   - thick = specifies the thickness of the outline.
///////////////////////////////////////////////////////////////////////////////
module SoccerBall(rad, thick)
{
    // Create the outline of the ball.
    Ball(rad, thick);

    // Create a dark pentagon in the center.
    circle(r = rad / 4, $fn = 5);

    // Add pentagons around the outer edge.
    for (i = [36:72:360])
    {
        rotate([0, 0, i]) translate([rad * .7, 0]) circle(r = rad / 4, $fn = 5);
    }
} // End SoccerBall().

///////////////////////////////////////////////////////////////////////////////
// Star()
//
// Star with one point up.  Always has one point pointing
// directly up.
//
// ARGUMENTS:
//   - p  = number of points for the star.
//   - r1 = radius of inside points of star.
//   - r2 = radius of outside points of star.
///////////////////////////////////////////////////////////////////////////////
module Star(p = 5, r1 = 4, r2 = 10)
{
    phase = 180 / p + 90;
    s = [for (i = [0 : p * 2])
        [
        (i % 2 == 0 ? r1 : r2) * cos(phase + 180 * i / p),
        (i % 2 == 0 ? r1 : r2) * sin(phase + 180 * i / p)
        ]
    ];

    polygon(s);
} // End Star().

///////////////////////////////////////////////////////////////////////////////
// RoundedCube()
//
// Generate a cube with all edges and corners rounded to the same given radius.
//
// ARGUMENTS:
//   - size  = the size of the cube.  If a scalar value is given, then the
//             generated object is a cube with all sides of the given length.
//             If a vector is given, then the generated object uses the
//             X, Y, and Z values provided in the vector.
//   - radius = radius of the cube's rounded edges and corners.
//   - center = set to true to center the cube at the origin-
///////////////////////////////////////////////////////////////////////////////
module RoundedCube(size = [1, 1, 1], radius = 0.5, center = false)
{
    // If single value, convert to [x, y, z] vector.
    size = (size[0] == undef) ? [size, size, size] : size;

    xlate = (center == false) ?
        [radius, radius, radius] :
        [
            radius - (size[0] / 2),
            radius - (size[1] / 2),
            radius - (size[2] / 2)
    ];

    translate(xlate)
    minkowski() {
        cube(size = [
            size[0] - (radius * 2),
            size[1] - (radius * 2),
            size[2] - (radius * 2)
        ]);
        sphere(r = radius);
    }
} // End RoundedCube().

///////////////////////////////////////////////////////////////////////////////
// HockeyStick()
//
// Generate a hockey stick.
//
// ARGUMENTS:
//   - rad   = specifies the radius.
//   - thick = specifies the thickness of the outline.
///////////////////////////////////////////////////////////////////////////////
module HockeyStick(rad, thick)
{
    hsradius = .5;
    hsthick = .05;

    // Move into position and resize.
    translate([rad * .5, -rad * .8]) resize([rad * 1.5, rad * 1.5])
    {
        // Create the paddle.  Project the paddle onto the XY plane.
        // Had to do this since minkowski only works with 3D objects.
        projection(cut = false)
        {
            minkowski()
            {
                translate([0, 0, 10]) cylinder(r = hsradius, h = hsthick);
                translate([0, 0, 10]) cube([3.5 * thick, 1 * thick, hsthick]);
            }
        }
        // Add the handle (shaft).
        translate([0*hsradius / 2, -hsradius]) rotate([0, 0, 45])
            square([1.2 * thick, 2 * rad]);
    }
} // End HockeyStick().

///////////////////////////////////////////////////////////////////////////////
// GolfClubAndBall()
//
// Generate a golf club and ball.
//
// ARGUMENTS:
//   - rad   = specifies the radius.
//   - thick = specifies the thickness of the outline.
///////////////////////////////////////////////////////////////////////////////
module GolfClubAndBall(rad, thick)
{
    hsradius = .5;
    hsthick = .05;

    translate([0, -rad * .7])
    {
        rotate([0, 0, 5]) square([thick, rad * 1.3]);
        projection(cut = false)
        {
            minkowski()
            {
                translate([0, 0, 10]) cylinder(r = hsradius, h = hsthick);
                translate([0, 0, 10]) cube([rad * .4 - 2 * hsradius, 2 * (thick - hsradius), hsthick]);
            }
        }
        translate([4 * thick, rad * .8]) circle(r = thick);
    }
} // End GolfClubAndBall().

///////////////////////////////////////////////////////////////////////////////
// Karate()
//
// Generate one of 7 karate based icons.
//
// ARGUMENTS:
//   - index = specifies the radius the icon to display as follows:
//     - 12 = Karate kick 1
//     - 13 = Karate kick 2
//     - 14 = Karate kick 3
//     - 15 = Karate pose
//     - 16 = Karate nunchucks
//     - 17 = Karate belt
//     - 18 = Karate belt (mirror)
//
//   - size  = specifies the size of the icon.
///////////////////////////////////////////////////////////////////////////////
module Karate(index, size)
{
    translate([-size * .8, -size * .8]) resize([size * 1.6, size * 1.6])
        SelectThing(index - KARATE_KICK_1)
    {
        import("kick-1.svg");
        import("kick-2.svg");
        import("kick-3.svg");
        import("pose-1.svg");
        import("nunchuck-1.svg");
        import("belt-1.svg");
        import("belt-1.svg");
    }
} // End Karate().

///////////////////////////////////////////////////////////////////////////////
// Books()
//
// Generate one of 6 book based icons.
//
// ARGUMENTS:
//   - index = specifies the radius the icon to display as follows:
//     - 19 = Book 1
//     - 20 = Book 2
//     - 21 = Book 3
//     - 22 = Book 4
//     - 23 = Book 5
//     - 24 = Book 6
//
//   - size  = specifies the size of the icon.
///////////////////////////////////////////////////////////////////////////////
module Books(index, size)
{
    translate([-size * .8, -size * .8]) resize([size * 1.6, size * 1.6])
        SelectThing(index - BOOK_1)
    {
        import("Book-1.svg");
        import("Book-2.svg");
        import("Book-3.svg");
        import("Book-4.svg");
        import("Book-5.svg");
        import("Book-6.svg");
    }
} // End Books().

///////////////////////////////////////////////////////////////////////////////
// Create the trophy.
///////////////////////////////////////////////////////////////////////////////
!translate([0, 0, BaseHeight]) Trophy();

```


[User]
I'd like to design a wall-mounted flag pole holder, and I'm hoping you can help me create a parametric OpenSCAD file for it. I need to be able to adjust a lot of different things, so I want to make sure it's all parameterized.

Here's what I'm thinking:

First, for the tube that holds the flagpole:
*   I need to control the inner diameter, which will match the flagpole diameter.
*   I need to set the thickness of the tube walls.
*   The length of the tube, from where it attaches to the wall to the end.
*   And finally, the angle of the tube relative to the wall.

Then there's the wall plate, which attaches to the wall and holds the tube:
*   I need to be able to specify the width of this plate.
*   The height of the plate.
*   The thickness of the plate.
*   I also need to have screw holes for mounting, so I need to define the diameter of the screws I'll be using, as well as the diameter of the screw heads.
*   It would be great to have an option for a drain hole, to let water out if it rains.

I'd like to control the number of fragments used to render circles and curves to make sure it's a reasonable level of detail.

I think that covers everything. If I'm missing anything please let me know. Please let me know what libraries will be needed for this design.

[Assistant]
flagholder.scad:
```
/* [General Settings] */
//number of fragments 64 should be great
$fn=32;//[16:1:128]
/* [Tube Settings] */
//diameter of the flagpole in mm = inner diameter of tube
poleDiameter = 32; //[10:1:40]
//the thickness of the tube
tubeThickness = 6; //[2:0.5:10]
//The length of the tube (longest distance from top to plate)
tubeLength = 120; //[60:1:160]
//the angle of the tube
tubeAngle = 45; //[35:1:90]
/* [Wall Plate settings] */
//the width of the wall plate (x)
wallPlateWidth = 80; //[50:1:150]
//the height of the ground plate (z)
wallPlateHeight = 120; //[70:1:150]
//the depth/thickness of the ground plate (y)
wallPlateDepth = 8; //[2:1:15]
//the diameter of the screws that will be used
screwDiameter = 4; //[2:0.5:15]
//the diameter of the head of the screws
screwHeadDiameter = 10; //[4:0.5:20]
//drainHole for rainwater?
drainHole = "yes"; //[yes,no]

module screwHole(){
  translate([0,0,1.4]){
    translate([0,0,-29.999])
    cylinder(h=30,d=screwDiameter);
    cylinder(h=1.6,d1=screwDiameter, d2 = screwHeadDiameter);
    translate([0,0,1.599])
    cylinder(h=20,d=screwHeadDiameter);
  }
}

module screwHoles(x,y,z) {
  screwX = x/2-screwHeadDiameter/2-5;
  screwY = z/2-screwHeadDiameter/2-5;

  union() {
    translate([screwX,screwY])
      screwHole();
    translate([-screwX,screwY])
      screwHole();
    translate([screwX,-screwY])
      screwHole();
    translate([-screwX,-screwY])
      screwHole();
  }
}

module wallPlate() {
  x=wallPlateWidth;
  z=wallPlateHeight;
  y=wallPlateDepth;
  hw=wallPlateWidth/2;
  hh=wallPlateHeight/2;
  difference(){
    translate([-hw,-hh,0]){
      cube([x,z,y]);
    }
    translate([0,0,wallPlateDepth-8]){
      translate([hw+6,-hh-1,0])
      rotate([0,-45,0])
        cube([10,z+2,y*2]);

      mirror([1,0,0])
      translate([hw+6,-hh-1,0])
      rotate([0,-45,0])
        cube([10,z+2,y*2]);

      translate([-hw-1,hh+6,0])
      rotate([45,0,0])
        cube([x+2,10,y*2]);

      mirror([0,1,0])
      translate([-hw-1,hh+6,0])
      rotate([45,0,0])
        cube([x+2,10,y*2]);
    }
    screwHoles(x,y,z);
  }

}

module outerTube(){
  diam = poleDiameter+(tubeThickness*2);
  h1=tubeLength;

    union(){
      cylinder(h= h1, d=diam);
      translate([0,0,h1-15])
      cylinder(h= 15, d1=diam, d2 = diam+6);
      translate([0,diam/2-1,0])
      support();
    }

}

module support() {
  tiltAngle = tubeAngle>65? -tubeAngle: -tubeAngle-8;
  translate([0,0,tubeLength/1.4])
  difference(){
    rotate([tiltAngle,0,0])
    translate([-3,0,-80])
    cube([6,100,80]);
    translate([-5,-90,-140])
    cube([10,90,142]);
  }
  //translate([0,0,tubeLength/1.45])
  //  translate([-5,-80,-130])
  //  cube([10,80,132]);
}

module innerTube(){
  diam = poleDiameter;
  h1=tubeLength;
  union(){
    translate([0,0,-2.2])
    cylinder(h= h1+3, d=diam);
    translate([0,0,h1-14])
    cylinder(h= 15.001, d1=diam, d2 = diam+4);
    //translate([0,0,h1+3])
    //cylinder(h= 6, d1=diam-2, d2 = diam+9);
  }
}
module straightTube(){
  diam = poleDiameter+(tubeThickness*2);
  translate([0,diam/2,-1])
  difference(){
    outerTube();
    innerTube();
  }
}
module tube (){
  difference(){
    rotate ([-90+tubeAngle,0,0])
      straightTube();
    translate([-40,-52,-120.01])
      cube([80,150,120]);
  }

}

module drainHole(){
  if(drainHole == "yes"){
  translate([0,4,-1.5])
  difference(){
    translate([0,0,10])
      rotate([90,45,0])
        cube([6,6,30], center = true);
    translate([-6,-16,0])
      cube([12,32,9]);
  }
}

}

module total(){
  difference(){
    union(){
      translate([0,0,wallPlateDepth])
      tube();
      translate([0,wallPlateHeight/4,0])
      wallPlate();
    }
    drainHole();
  }
}

total();

```


[User]
I need an OpenSCAD design for a hose adapter, and it needs to be fully parametric. Basically, it should have three sections: a larger diameter section on one end, a smaller diameter section on the other end, and a smoothly transitioning section in the middle connecting them.

Here's what I need to be able to control:

*   The outer diameter of the larger section.
*   The outer diameter of the smaller section.
*   The wall thickness, which should be uniform throughout.
*   The length of the larger diameter section.
*   The length of the smaller diameter section.
*   The length of the transition section.

The inside diameters should be calculated automatically from the outer diameters and the wall thickness.

I need to be able to set all these values using the OpenSCAD customizer.

I don't need anything fancy, just a clean, functional model. Please, could you also ensure that the curves are reasonably smooth by using `$fn`? I'm not sure how to handle that within a library.

I'm okay if it is a single file. I also don't have a preference for specific OpenSCAD libraries to use, but if you think it might simplify anything, feel free to use them.

[Assistant]
HoseAdaptor.scad:
```
// Any-size Hose Adapter
// Copyright Chris Cogdon 2023
// Licence: CC BY-SA 4.0
// Full licence: https://creativecommons.org/licenses/by-sa/4.0/legalcode
//
larger_OD = 40;
larger_length = 20;
smaller_OD = 20;
smaller_length = 20;
transition_length = 30;
thickness = 1.6;

// Dummy code to separate parameterized values.
module separator () {}

// Smoothness of curves. Larger values will cause larger rendering times. 200 is already
// pretty big.
$fn=200;
// A very small value to make differences appear correctly in a preview
epsilon=0.01;

module larger_segment() {
    linear_extrude(height=larger_length)
        difference() {
            circle(d=larger_OD);
            circle(d=larger_OD-thickness*2);
        }
}

module transition_segment() {
    difference(){
        linear_extrude(height=transition_length, scale=smaller_OD/larger_OD)
            circle(d=larger_OD);
        translate([0, 0, -epsilon])
            linear_extrude(height=transition_length+epsilon*2,
                    scale=(smaller_OD-thickness*2)/(larger_OD-thickness*2))
                circle(d=larger_OD-thickness*2);
    }
}

module smaller_segment() {
    linear_extrude(height=smaller_length)
        difference() {
            circle(d=smaller_OD);
            circle(d=smaller_OD-thickness*2);
        }
    }

larger_segment();
translate([0, 0, larger_length]) transition_segment();
translate([0, 0, larger_length + transition_length]) smaller_segment();

```


[User]
Hey, I'm looking to create a modular storage system using OpenSCAD. I've seen some cool designs with different shaped cells, and I'd love to be able to customize the layout and height of each cell.

Ideally, I'd like the system to support two basic cell shapes: squares and hexagons. For each of these shapes, I want the ability to either manually specify the position and height of each cell, or have the system randomly generate a layout based on some rules. For the manual generation, I'd give a list of coordinates and corresponding heights. For random generation, I would need to set how many cells, rows, and have height limits (min/max).

Could you generate a parametric OpenSCAD design that allows me to do this? Let's break down the details:

*   **Cell Shapes:** The user should be able to select either "Square" or "Hexagon" as the base shape for the cells.
*   **Generation Methods:** The user should be able to select "random" or "manual" for cell layout generation
*   **Square Cell Parameters:** If "Square" is chosen, the user should be able to set the `width` and `length` of each square cell (they can be different if I want, but don't have to be). There also needs to be a `thickness` parameter to define the wall thickness of each cell.
*   **Hexagon Cell Parameters:** If "Hexagon" is chosen, the user should be able to set the `diameter` of the circumscribing circle of each hexagon. It also needs a `thickness` parameter (which may need to be used in calculating wall thickness, since hexagons have flat edges).
*   **Manual Generation:** If "manual" generation is chosen, the user will input a list called `group_manual`, where each item in the list is a list specifying coordinates (column, row), followed by the height of the cell. For example, `[[0,0],30]` would mean a cell at column 0, row 0, with a height of 30.
*   **Random Generation:** If "random" is chosen, the user should be able to set the number of random cells `number_random`, rows `row_random`, a `height_limit_high` and `height_limit_low` for the random height generation.
*   **Output:** The OpenSCAD script should generate all cells in place based on the parameters above.

I think that covers everything I need. I'd like all of the code to be in a single .scad file if possible. I'm not using any specialized OpenSCAD libraries, so I think that's not an issue. I'm looking forward to seeing what you come up with!

[Assistant]
container_final.scad:
```
//模块化收纳盒 modular container

//选择形状和生成方式
type="Hexagon"; //["Square","Hexagon"]
how_to_generate="manual"; //["random","manual"]
//单个方形长宽
width=50;
length=50;
//单个六棱柱直径
diameter=50;
//厚度
thickness=2;
thickness_hexagon=thickness/sin(60);

//自定义格子的位置和对应的高度[[column,row],height]
group_manual=[
        [[0,0],30],
        [[1,0],40],
        [[2,0],50],
        [[0,1],80],
        [[1,1],70],
        [[2,1],60],
        [[0,2],90],
        [[1,2],100],
        [[2,2],110],
        ];

//随机生成格子总数
number_random=6;
//行数
row_random=1;
//每行个数
column=floor(number_random/row_random);
//随机高度上限
height_limit_high=150;
//随机高度下限
height_limit_low=50;
//随机高度
rand = rands(height_limit_low,height_limit_high,number_random);
//随机生成位置
coord=[
    for ( i=[0:column])
    for ( j=[0:row_random-1])
    [i,j]
    ];
//生成格子的位置和对应的高度
group_random = [ for (i=[0:number_random-1]) [coord[i],rand[i]]];

//生成收纳盒
generator();

//生成方法
module generator(){
    if (type=="Square" && how_to_generate=="random"){
        number=number_random;
        generate_square(group_random,number);
    }
    if(type=="Square" && how_to_generate=="manual"){
        number=len(group_manual);
        generate_square(group_manual,number);
    }
    if (type=="Hexagon" && how_to_generate=="random"){
        number=number_random;
        generate_hexagon(group_random,number);
    }
    if(type=="Hexagon" && how_to_generate=="manual"){
        number=len(group_manual);
        generate_hexagon(group_manual,number);
    }
}

//生成方盒
module generate_square(group,number){
    for (i=[0:number-1]){
        translate([group[i][0][0]*length-thickness*group[i][0][0],group[i][0][1]*width-thickness*group[i][0][1],0])
            square(group[i][1]);
    }
}

//生成六边盒
module generate_hexagon(group,number){
    for (i=[0:number-1]){
        translate([
        group[i][0][0]*width*sin(60)-thickness*group[i][0][0]-thickness*(group[i][0][1]%2)/2+(group[i][0][1]%2)*width*sin(60)/2,
        group[i][0][1]*((width*(1+cos(60)))/2)-(thickness_hexagon-thickness/2*tan(30))*group[i][0][1],0
        ])
            hexagon(group[i][1]);
      }
}
//单个方盒
module square(height){
    difference(){
        cube([length,width,height]);
        translate([thickness,thickness,thickness])
        cube([length-thickness*2,width-thickness*2,height]);
    }
}
//单个六边盒
module hexagon(height){
    rotate([0,0,30])
    difference(){
        cylinder(height,diameter/2,diameter/2,$fn=6);
        translate([0,0,thickness])
        cylinder(height,diameter/2-thickness_hexagon,diameter/2-thickness_hexagon,$fn=6);
    }
}
```


[User]
Hey, I'm looking to design a modular organizer system based on a 38.5mm grid, and I'd like to make some custom parts. I've seen some designs already, and they're great, but I need to be able to adjust a bit more.

First, I need a way to generate the base trays. I'd like to be able to specify the length, width, and height of the tray, as well as the wall thickness. The inside dimensions, which determine how many grid units it holds, should always be a multiple of 38.5mm and the outside dimensions would be determined by those dimensions + wall thickness *2. The height should also be user defined as noted above. I’d like the wall thickness to be configurable and default to 1.6mm. Can you generate the necessary OpenSCAD code that allows me to customize these parameters?

I'm thinking of going beyond just the basic trays later, so I'd like to keep this code parametric and easy to extend. Also it would be useful if the default units were in mm.

I also want to make sure I follow the general recommendations I found, like making sure walls are at least 8mm tall for components to fit well, and I want to use 4 perimeters using a 0.4mm nozzle and 0.2mm layers. I don’t think the generated code needs to worry about the perimeters and such, though - that’s handled by my slicer, right?

[Assistant]
Customizable_Basic_DMO_Tray-Base.scad:
```
//Customizable basic DMO tray or base (mm)
//
length = 38.5;     // Default length
width = 38.5;       // Default width
height = 36.6;      // Default height
wallThickness = 1.6; // Default wall thickness

// Function to create box
module createBox() {
    difference() {
        // Outer box
        cube([length, width, height], center=false);

        // Inner box to hollow out the container based on wall thickness
        translate([wallThickness, wallThickness, wallThickness])
        cube([length - 2 * wallThickness, width - 2 * wallThickness, height], center=false);
    }
}

// Call the function to create the storage box
createBox();

```


[User]
Okay, I'd like to get an OpenSCAD design for a flexible battery holder. This will be similar to the "flexbatter" design I've seen, but I want it to be completely parametric, including the pre-set battery options, and I want to be able to select a pre-set from a dropdown or similar. I've looked at the original design, and the re-worked version, and want to incorporate the best of both.

Here's a breakdown of what I need:

*   **Parametric Battery Size:** The design should be able to handle different cylindrical battery sizes and configurations, such as:
    *   Number of compartments side-by-side (`n`).
    *   Number of cells within each compartment (`m`).
    *   Cell length (`l`).
    *   Cell diameter (`d`).
    *   Relative cell height within the holder (`hf`).
*   **Flexible Printed Spring:** Instead of a metal spring, there needs to be a built-in flexible plastic spring at the negative terminal. This spring needs to be designed to accommodate different cell sizes, and should be parametric (length and width).
*   **Wire Channels:** The design should include channels for wires both along the bottom of the holder, and traversal wire channels. These channels should be parametric in terms of their relative position.
*   **Contact Points:**  The design should allow for easy creation of contact points for both the positive and negative poles, with a bulged/spherical contact on either end for the battery, and an easily accessible point on the outside for wiring. I don't need actual contact parts, but the design should allow for the easy inclusion of wire.
*   **Mounting Holes:**  Conical screw holes in the corners are needed for mounting. These should also be parametric in diameter.
*   **Deepening Feature:**  I need the ability to include a "deepening" feature for improved side grip on batteries, with a parameter for relative deepening and radius.
*   **Pre-sets:** I want to be able to select from a number of pre-set battery options (e.g., AA, AAA, C, D, 18650, etc.) from a dropdown menu, similar to how you can in the customizer for the re-worked design, and **when a preset is selected the individual custom parameters should be ignored.**

The pre-sets I need are as follows:
AAAx1,1xAAA,AAAx2,1xAAAx2,AAAx3,1xAAAx3,AAAx4,1xAAAx4,2xAAA,2xAAAx2,3xAAA,1xAA,2xAA,AAx1,AAx2,1xAAx2,AAx3,1xAAx3,AAx4,1xAAx4,2xAAx2,3xAA,CR123Ax1,3xC,Cx1,1xC,1xCx2,1xCx3,1xCx4,2xC,2xCx2,Cx2,D,18650Px1,18650Px2,18650Px3,18650Px4,18650x1,1x18650,18650x2,1x18650x2,18650x3,1x18650x3,18650x4,1x18650x4,2x18650,2x18650x2,26650x1,26650x2,26650x3,26650x4,1x13400,2x13400,13400x1,13400x2,13400x3,13400x4.

I also need parameters for extrusion width and extrusion height.

This is all the information I can think of. I don't want to modify an existing design (other than using them as a guide), but instead start from scratch with a design that handles the parameterisation of the preset selection, and that is able to be used in the Customizer. I don't need any libraries to be included.

[Assistant]
flexbatter2.1.scad:
```
/*

  FLEXBATTER: Flexing battery holder with built-in spring

  This file generates battery holders for arbitrary cylindrical sizes.
  The number of batteries compartments, the number of batteries in each compartment
  and the battery size are fully parametrized.

  The usual metallic spring at the minus pole is replaced by a
  flexible printed spring, which is pressing the contacts firmly to
  the battery.

  The contacts for the plus and minus pole can easily be made by
  a few windings of the uninsulated ends of the connecting wires.
  Each battery compartment contains are several holes to the outside
  as well ad to the neighboring compartments, through which connecting
  wires can be passed for easy configuring of parallel, serial or
  balanced-serial battery packs.

  The preconfigured battery sizes are:
  AA, AAA, C, D, 18650(Li-Ion), 18650P(protected Li-Ion), CR123A(16340)

  Given that the printed plastic spring needs to be flexible, ABS is the material
  of choice here.

  When adding new presets, add them to both:
     1. create_this_preset and
     2. presets
  in the same order they appear in "module flexbatter()"

  2014-09-09 Heinz Spiess, Switzerland
  2015-07-25 multi-cell compartments added
  2023-02-21 Updated to make presets selectable (PPL)

  released under Creative Commons - Attribution - Share Alike licence (CC BY-SA)

*/

/* [Presets] */
// Cells High - Cell Type - Cells wide (If a preset other than "Custom", the parameters below are IGNORED)
create_this_preset="Custom"; //[Custom,AAAx1,1xAAA,AAAx2,1xAAAx2,AAAx3,1xAAAx3,AAAx4,1xAAAx4,2xAAA,2xAAAx2,3xAAA,1xAA,2xAA,AAx1,AAx2,1xAAx2,AAx3,1xAAx3,AAx4,1xAAx4,2xAAx2,3xAA,CR123Ax1,3xC,Cx1,1xC,1xCx2,1xCx3,1xCx4,2xC,2xCx2,Cx2,D,18650Px1,18650Px2,18650Px3,18650Px4,18650x1,1x18650,18650x2,1x18650x2,18650x3,1x18650x3,18650x4,1x18650x4,2x18650,2x18650x2,26650x1,26650x2,26650x3,26650x4,1x13400,2x13400,13400x1,13400x2,13400x3,13400x4]

/* [Custom] */
// number of compartments side by side
n=1;
// number of cells in one compartment
m=1;
// length of cell
l=65;
// diameter of cell
d=18;
// relative hight of cell (1=full diameter)
hf=0.75;
// screw hole diameter
shd=3;
// extra diameter space
eps=0.28;
// overhang to avoid lifting of cell
oh=0;
// extra spring length (needed for small cells)
el=0;
// relative position of traversal wire channels
xchan=[1/4,3/4];
// relative deepening for side grip of batteries
deepen=0;
// relative deepening radius
df=1;
// length correction for multicell compartments
lcorr=0;
// extrusion width
ew=0.56;
// extrusion height
eh=0.25;

$fn=24;
module END_OF_VARS(){};

presets=[
["Custom",[1,1,65,18,0.75,3,0.28,0,0,[1/4,3/4],0,1,0]],
["18650Px1",[1,m,70,18.4,0.75,3,0.28,0,0,[1/4,3/4],0,1,0]],
["18650Px2",[2,m,70,18.4,0.75,3,0.28,0,0,[1/4,3/4],0,1,0]],
["18650Px3",[3,m,70,18.4,0.75,3,0.28,0,0,[1/4,3/4],0,1,0]],
["18650Px4",[4,m,70,18.4,0.75,3,0.28,0,0,[1/4,3/4],0,1,0]],
["18650x1",[1,m,7,18.4,0.75,3,0.28,oh,0,[1/4,3/4],deepen,df,0.3]],
["18650x2",[2,m,7,18.4,0.75,3,0.28,oh,0,[1/4,3/4],deepen,df,0.3]],
["18650x3",[3,m,7,18.4,0.75,3,0.28,oh,0,[1/4,3/4],deepen,df,0.3]],
["18650x4",[4,m,7,18.4,0.75,3,0.28,oh,0,[1/4,3/4],deepen,df,0.3]],
["1x18650",[1,1,7,18.4,0.75,3,0.28,ew,0,[1/4,3/4],0.7,0.3,0.3]],
["1x18650x2",[2,1,7,18.4,0.75,3,0.28,ew,0,[1/4,3/4],0.7,0.3,0.3]],
["1x18650x3",[3,1,7,18.4,0.75,3,0.28,ew,0,[1/4,3/4],0.7,0.3,0.3]],
["1x18650x4",[4,1,7,18.4,0.75,3,0.28,ew,0,[1/4,3/4],0.7,0.3,0.3]],
["1xAA",[1,1,50.0,14.4,0.80,2.5,0.28,ew,0.5,[1/4,3/4],0.7,0.25,1.6]],
["1xAAA",[1,1,44.5,10.5,0.84,2,0.2,0.4,1,[0.5],0.7,0.25,1.6]],
["1xAAAx2",[2,1,44.5,10.5,0.84,2,0.2,0.4,1,[0.5],0.7,0.25,1.6]],
["1xAAAx3",[3,1,44.5,10.5,0.84,2,0.2,0.4,1,[0.5],0.7,0.25,1.6]],
["1xAAAx4",[4,1,44.5,10.5,0.84,2,0.2,0.4,1,[0.5],0.7,0.25,1.6]],
["1xAAx2",[2,1,50.0,14.4,0.80,2.5,0.28,ew,0.5,[0.5],0.7,0.25,1.6]],
["1xAAx3",[3,1,50.0,14.4,0.80,2.5,0.28,ew,0.5,[0.5],0.7,0.25,1.6]],
["1xAAx4",[4,1,50.0,14.4,0.80,2.5,0.28,ew,0.5,[0.5],0.7,0.25,1.6]],
["1xC",[1,1,49.6,26.4,0.75,3,0.28,ew,0.5,[0.5],0.67,0.07,2]],
["1xCx2",[2,1,49.6,26.4,0.75,3,0.28,ew,0.5,[0.5],0.67,0.07,2]],
["1xCx3",[3,1,49.6,26.4,0.75,3,0.28,ew,0.5,[0.5],0.67,0.07,2]],
["1xCx4",[4,1,49.6,26.4,0.75,3,0.28,ew,0.5,[0.5],0.67,0.07,2]],
["26650x1",[1,m,65.7,26.4,0.72,3,0.28,ew,0.5,[0.5],0.67,0.07,0]],
["26650x2",[2,m,65.7,26.4,0.72,3,0.28,ew,0.5,[0.5],0.67,0.07,0]],
["26650x3",[3,m,65.7,26.4,0.72,3,0.28,ew,0.5,[0.5],0.67,0.07,0]],
["26650x4",[4,m,65.7,26.4,0.72,3,0.28,ew,0.5,[0.5],0.67,0.07,0]],
["2x18650",[1,2,70,18.4,0.75,3,0.28,ew,0.5,[0.5],0.7,0.07,0]],
["2x18650x2",[2,2,70,18.4,0.75,3,0.28,ew,0.5,[0.5],0.7,0.07,0]],
["2xAA",[1,2,50.0,14.4,0.80,2.5,0.28,0.4,0.5,[0.5],0.7,df,1.6]],
["2xAAA",[1,2,44.5,10.5,0.84,2,0.2,0.4,1,[0.5],0.7,df,1.6]],
["2xAAAx2",[2,2,44.5,10.5,0.84,2,0.2,ew,1,[0.5],0.7,df,1.6]],
["2xAAx2",[2,2,44.5,10.5,0.84,2,0.2,ew,1,[0.5],0.7,df,1.6]],
["2xC",[1,2,49.6,26.4,0.75,3,0.28,ew,1,[0.5],0.7,df,2]],
["2xCx2",[2,2,49.6,26.4,0.75,3,0.28,ew,1,[0.5],0.7,df,2]],
["3xAA",[1,3,50.0,14.4,0.80,2.5,0.28,ew,0.5,[0.5],0.7,df,1.6]],
["3xAAA",[1,3,44.5,10.5,0.84,2,0.2,0.4,1,[0.5],0.7,df,1.6]],
["3xC",[1,3,49.6,26.4,0.75,3,0.28,ew,1,[0.5],0.7,df,2]],
["AAAx1",[1,m,44.5,10.5,0.84,2,0.2,oh,1,[0.5],deepen,df,1.6]],
["AAAx2",[2,m,44.5,10.5,0.84,2,0.2,oh,1,[0.5],deepen,df,1.6]],
["AAAx3",[3,m,44.5,10.5,0.84,2,0.2,oh,1,[0.5],deepen,df,1.6]],
["AAAx4",[4,m,44.5,10.5,0.84,2,0.2,oh,1,[0.5],deepen,df,1.6]],
["AAx1",[1,m,50.0,14.4,0.80,2.5,0.28,oh,0.5,[0.5],deepen,df,1.6]],
["AAx2",[2,m,50.0,14.4,0.80,2.5,0.28,oh,0.5,[0.5],deepen,df,1.6]],
["AAx3",[3,m,50.0,14.4,0.80,2.5,0.28,oh,0.5,[0.5],deepen,df,1.6]],
["AAx4",[4,m,50.0,14.4,0.80,2.5,0.28,oh,0.5,[0.5],deepen,df,1.6]],
["CR123Ax1",[1,m,35.1,16.7,0.75,3,0.28,oh,0.5,[0.5],deepen,df,0]],
["Cx1",[1,m,49.6,26.4,0.75,3,0.28,oh,0.5,[0.5],deepen,df,2]],
["Cx2",[2,m,49.6,26.4,0.75,3,0.28,oh,0.5,[0.5],deepen,df,2]],
["D",[n,m,61.5,34.0,0.75,3,0.28,oh,0.5,[0.5],deepen,df,0]],
["1x13400",[1,1,41.5,13.0,0.80,2.5,0.28,ew,0.5,[1/4,3/4],0.7,0.25,1.6]],
["2x13400",[1,2,41.5,13.0,0.75,3,0.28,ew,0.5,[0.5],0.7,0.07,0]],
["13400x1",[1,1,41.5,13.0,0.75,3,0.28,ew,0.5,[0.5],0.7,0.07,0]],
["13400x2",[2,1,41.5,13.0,0.75,3,0.28,ew,0.5,[0.5],0.7,0.07,0]],
["13400x3",[3,1,41.5,13.0,0.75,3,0.28,ew,0.5,[0.5],0.7,0.07,0]],
["13400x4",[4,1,41.5,13.0,0.75,3,0.28,ew,0.5,[0.5],0.7,0.07,0]]

];

// build a cube with chamfered edges
module chamfered_cube(size,d=1){
   hull(){
     translate([d,d,0])cube(size-2*[d,d,0]);
     translate([0,d,d])cube(size-2*[0,d,d]);
     translate([d,0,d])cube(size-2*[d,0,d]);
   }
}

// draw an arc width height h between radius r1..r2 and angles a1..a2
module arc(r1,r2,h,a1=0,a2=0){
     if(a2-a1<=180){
        difference(){
           cylinder(r=r2,h=h);
           translate([0,0,-1])cylinder(r=r1,h=h+2);
	   rotate(a2)translate([-r1-r2,0,-1])cube([2*(r1+r2),2*(r1+r2),h+2]);
	   rotate(a1+180)translate([-r1-r2,0,-1])cube([2*(r1+r2),2*(r1+r2),h+2]);
        }
     } else {
           difference(){
              cylinder(r=r2,h=h);
              translate([0,0,-1])cylinder(r=r1,h=h+2);
              intersection(){
	       rotate(a2)translate([-r1-r2,0,-1])cube([2*(r1+r2),2*(r1+r2),h+2]);
	       rotate(a1+180)translate([-r1-r2,0,-1])cube([2*(r1+r2),2*(r1+r2),h+2]);
	      }
           }
     }
}

/* sline - generate a "snake line" of width w and height h
  with a arbitrary sequence of segments defined by a radius and a turning angle

    angle[i] > 0  left turn / counter-clockwise
    angle[i] < 0  left turn / clockwise
    angle[i] = 0  straight segment with length radius[i]

  Heinz Spiess, 2014-09-06 (CC BY-SA)

*/
module sline(angle,radius,i,w,h){
   scale([angle[i]>=0?1:-1,1,1])
      let(r=abs(radius[i]))let(a=angle[i])
         translate([a?r:0,0,0]){
	    translate([-w/2,-r-0.01,0])cube([w,0.02,h]); // tiny overlap!
             // arc (r1,   r2,   h,a1=0,a2=0)
            if(a)arc(r1=r-w/2,r2=r+w/2,a2=0,a1=a,h=h);
	    else if(r>0)translate([-w/2,-r,0])cube([w,r,h]);
      if(i+1<len(angle))
           rotate(angle[i])
	      translate([a?-r:0,a?0:-r,0])
	         sline(angle,radius,i+1,w,h);
  }
}

//
//  FLEXBATTER:  Flexing battery holder with integrated plastic spring
//

module flexbatter(
  n=1,m=1,l=65,d=18,hf=0.75,shd=3,eps=0.28,oh=0,el=0,xchan=[1/4,3/4],deepen=0,df=1,lcorr=0
  ){

 $fn=24;
  w = (m>1?6:4)*ew;  // case wall thickness
  wz = 2;            // bottom wall thickness
  ws = 2*ew; // spring wall thickness
  ch = ws; // edge chamfering

  r = d/5+2*ws; // linear spring length (depends on sline() call!)
  L = m*l+lcorr;// corrected overall lenth
  lc = L/m;     // corrected cell length

   for(i=[0:n-1])translate([0,i*(d+2*w-ws),0]){ // generate n battery cases
      difference(){

         union(){
            difference(){
               // main body
               translate([0,-w-d/2,0])
	          chamfered_cube([L+w,d+2*w+(i<n-1?ws:0),hf*d+wz+ch],ch);
	       // main cavity
               let(jmin=deepen>0?0:-1)
	       for(j=[0:m-1])translate([j*lc,0,0])hull(){
                  translate([-0.01,-d/2+(j>jmin?oh:0),wz])cube([lc/4,d-(j>jmin?2*oh:0),d+1]);
                  translate([lc*0.75,-d/2+(j<m-1?oh:0),wz])cube([lc/4+0.01,d-(j<m-1?2*oh:0),d+1]);
               }
	       // cavity for locating plastic spring
               translate([-1,-d/2,-1])cube([2,d,d+wz+2]);
	       // small cylindrical carving of walls and bottom
	       translate([-1,0,d/2+wz])rotate([0,90,0])cylinder(r=d/2+eps,h=L+1);
            }

            // plastic spring for minus pole
            for(sy=[-1,1])scale([1,sy,1])let(D=d+2*w-2*ws-0.7){
               translate([ch,d/2+w-ws/2,0])rotate(-90)
		  //sline([90,0,120,90,120,90,0],[d/8+2,d/6,d/8-1,d/8,-d/8,d/8,d/2],0,ws,hf*d+w);
		  sline([0,180,0,180,0,-180,0,90,0],[r+ch+el,D/4,el,D/12,el/2,D/12,1+el/2,D/5,D/3],0,ws,hf*d+wz);

            }
         }
         // lower and upper holes for contacts
         for(z=[-2*ws,2*ws])
            translate([-2*ws,-w,wz-ws/2+d/2+z])cube([L+2*w+2,2*w,ws]);

         // longitudinal bottom wire channel
         translate([-2*ws,0,0])rotate([0,90,0])cylinder(r=wz/2,h=L+w+2+r,$fn=5);

         // traversal bottom wire channels
         for(x=L*xchan)translate([x,-d/2-w-1,-eh]) rotate([-90,0,0])cylinder(r=wz/2,h=d+2*w+ws+2,$fn=6);

         // grip deepening
	if(deepen!=0)
	    for (j=[(deepen>0?0:m-1):m-1])
	    let(adeepen=deepen>0?deepen:-deepen)
            translate([j*lc+lc/2-0.5,-d/2-w-0.01,wz+d+df*l])
    rotate([-90,0,0]){
	          cylinder(r=df*l+adeepen*d,h=d+2*w+2*ws+2,$fn=72);
	          if(i==0)cylinder(r1=df*l+adeepen*d+ch,r2=df*l+adeepen*d,h=ch+0.02,$fn=72);
	          if(i==n-1)translate([0,0,d+2*w-ch])cylinder(r2=df*l+adeepen*d+ch,r1=df*l+adeepen*d,h=ch+0.02,$fn=72);

               }
         // conical screw holes in corners
         for(x=[7+shd,L-2*shd])for(y=[-d/2+shd,d/2-shd])
             translate([x,y,-1]){
                cylinder(r=shd/2,h=wz+2);
                translate([0,0,wz-shd/2+1])cylinder(r1=shd/2,r2=shd,h=shd/2+0.01);
             }

         // holes for wires passing inside
        for(sy=[-1,1])scale([1,sy,1]){
            translate([L-1,-d/2,wz])cube([w+2,2,2]);
            for(x=[3,L-7])translate([x,-d/2-w-ws-1,wz])cube([3,w+ws+3,2]);
                translate([3,-d/2+w/2-0.75,-1])cube([3,1.5,wz+2]);
                translate([-0.5,-d/2+w/2,0])rotate([0,90,0])cylinder(r=w/2,h=6.5,$fn=5);
         }

         // engrave battery symbol
        for(j=[0:m-1])translate([j*lc,0,0]){
            translate([w+l/2,d/4+1,wz])cube([l/5,d/4.5,4*eh],true);
            translate([w+l/2+l/10,d/4+1,wz])cube([d/7,d/10,4*eh],true);
	    // engrave plus symbol
            let(sy=(l>12*shd)?1:-1){ // for short batteries +- on the side
	       translate([w+l/2+l/(sy>0?5:10),sy*(d/4+1),wz]){
	          cube([1,d/4,4*eh],true);
	          cube([d/4,1,4*eh],true);
               }
	    // engrave minus symbol
	       translate([w+l/2-l/(sy>0?5:10),sy*(d/4+1),wz])
	          cube([1,d/4,4*eh],true);
            }
        }
      }
      // horizontal contact bulges (+ and - pole)
      for(x=[-0.3,L])
         hull()for(y=[-3+el,3-el])
            translate([x,y,wz+d/2])sphere(r=ws);

      // vertical contact bulge (+ pole only)
      if(0)hull()for(z=[-3+el,3-el])for(x=[0,w-ws])
            translate([L+x,0,wz+d/2+z])sphere(r=ws);
   }
}

// This is the Custom/Preset decision
if(create_this_preset=="Custom"){
    flexbatter(n,m,l,d,hf,shd,eps,oh,el,xchan,deepen,df,lcorr);
}else{
    list = [ for (i = presets) if (i[0]==create_this_preset) i];
    n=list[0][1][0];

    flexbatter(n=list[0][1][0],m=list[0][1][1],l=list[0][1][2],d=list[0][1][3],hf=list[0][1][4],shd=list[0][1][5],eps=list[0][1][6],oh=list[0][1][7],el=list[0][1][8],xchan=list[0][1][9],deepen=list[0][1][10],df=list[0][1][11],lcorr=list[0][1][12]);
}
```


[User]
Okay, so I'm looking to create a customizable tool organizer, and I want it to be easily adjustable for different sized tools. I'm thinking something along the lines of what I've already started, but more flexible.

I'd like you to generate a parametric OpenSCAD design for this. The core idea is that it will be a collection of rectangular compartments, each with rounded corners. The important bits are:

*   **Compartments:** Each compartment will have a position (x, y), a size (x, y, z), and an optional corner radius. The user should be able to define an array of these compartments and their characteristics, like I've already done in my example using the `compartments` array.
*   **Wall Thickness:** The walls of the compartments should have a consistent thickness, defined by a number of 'wall lines' multiplied by the nozzle size.
*   **Bottom Thickness:** The bottom of the organizer should also have a defined thickness, determined by a number of layers times the layer height.
*   **Rounded Corners:** Each compartment should have rounded corners, and the radius should be a parameter that can be set individually per compartment or globally using a default value.
*   **Parametric:** The design should be fully parametric, so I can easily change things like nozzle size, layer height, wall lines, and the overall dimensions of each compartment.

Here's a breakdown of parameters I need to be able to customize:

*   `nozzleSize`: The size of the 3D printer nozzle.
*   `wallLines`: The number of lines used to create the compartment walls.
*   `layerHeight`: The height of each 3D printed layer.
*   `bottomLayers`: The number of layers used for the bottom.
*   `cornerRadiusDefault`: The default radius for the rounded corners if not specified per-compartment.
*   `compartments`: An array of compartment definitions, each including position (x, y), size (x, y, z), and an optional corner radius.

I'm currently using this logic for determining wall thickness and bottom thickness:
```
wallThickness = wallLines * nozzleSize;
bottomThickness = bottomLayers * layerHeight;
```

and this logic for calculating the inner dimensions of each compartment:
```
makeCompartmentShape(
                [dimensions[0] - 2 * wallThickness, dimensions[1] - 2 * wallThickness, dimensions[2]],
                cornerRadiusOuter - wallThickness);
```
This should all be in one or more related `.scad` files. I won't need to specify any libraries myself since you're generating all the code, but please let me know if there's any you're using so that I can include them if I decide to make my own modifications in the future.

[Assistant]
ToolOrganizer.scad:
```
// Generator for tool organizers

nozzleSize              = .6;
wallLines               = 2;
layerHeight             = .25;
bottomLayers            = 6;
cornerRadiusDefault     = 5;

wallThickness = wallLines * nozzleSize;
bottomThickness = bottomLayers * layerHeight;

// Compartment structure: [position: x, y], [size: x, y z], optional cornerRadius
compartments = [
    [[30, -30], [60, 60, 50]],
    [[105 - 2 * wallThickness, -7.5], [30, 15, 80]],
    [[105 - 2 * wallThickness, -27.5 + wallThickness], [30, 25, 70]],
    [[75 - wallThickness, -20 + wallThickness / 2], [30, 40 - wallThickness, 80]],
    [[85 - wallThickness, -50 + wallThickness], [50, 20 + 2 * wallThickness, 70]],
    [[35, -75 + wallThickness], [50, 30, 20], 10],
    [[75 - wallThickness, -75 + wallThickness], [30, 30, 40]],
    [[100 - 2 * wallThickness, -70 + wallThickness], [20, 20, 30], 10],
];

$fa                     = $preview ? 5 : 2.5; // Angle between fragments in an arc
$fs                     = $preview ? 1.5 : 0.5; // Minimum size of fragments in an arc

union() {
    for (compartment = compartments) {
        cornerRadius = len(compartment) >= 3 ? compartment[2] : cornerRadiusDefault;
        makeCompartment(compartment[0], compartment[1], cornerRadius);
    }
}

module makeCompartment(position, dimensions, cornerRadiusOuter) {
    translate([position[0], position[1], dimensions[2] * 0.5]) {
        difference() {
            makeCompartmentShape(dimensions, cornerRadiusOuter);
            translate([0, 0, bottomThickness]) {
                makeCompartmentShape(
                [dimensions[0] - 2 * wallThickness, dimensions[1] - 2 * wallThickness, dimensions[2]],
                cornerRadiusOuter - wallThickness);
            }
        }
    }
}

module makeCompartmentShape(dimensions, cornerRadius) {
    cylOffsets = [dimensions[0] / 2 - cornerRadius, dimensions[1] / 2 - cornerRadius];
    hull() {
        translate([-cylOffsets[0], -cylOffsets[1], 0]) cylinder(h = dimensions[2], r = cornerRadius, center = true);
        translate([-cylOffsets[0], cylOffsets[1], 0]) cylinder(h = dimensions[2], r = cornerRadius, center = true);
        translate([cylOffsets[0], -cylOffsets[1], 0]) cylinder(h = dimensions[2], r = cornerRadius, center = true);
        translate([cylOffsets[0], cylOffsets[1], 0]) cylinder(h = dimensions[2], r = cornerRadius, center = true);
    }
}

```


[User]
I need an OpenSCAD design that helps me level my 3D printer bed. I've been using a simple one with a grid of squares, but I'd like something more tailored to my printer's probe points. I also want it to be easily customizable for different printer sizes and probe configurations.

Specifically, I'd like the design to produce a grid of squares, each composed of an inner solid square, a small gap, and an outer outline square. The key is that I need to define the exact x and y coordinates for each square in the grid, rather than relying on a simple evenly spaced grid. These x and y locations should be parameters, so I can specify them individually. Additionally, I need to control the size and thickness of the squares as well as the gap between the inner solid square and the outline.

So, the parameters should include:

*   A list of x coordinates (one for each square)
*   A list of y coordinates (one for each square)
*   The width/height of the inner solid square
*   The thickness of the squares
*   The gap between the inner solid square and the outer outline
*   The width of the outer outline

I would also like the design to be modular, so it's easy to reuse the square element in other designs, if needed. Basically, I'd like a module for the individual square, and a top level module that uses this square module, taking in the lists of coordinates.

I don't think I need any libraries for this, but I want to make sure to point out that the squares should be rendered in the correct location in space, given the x and y coordinates passed to the top level module.

Can you help me create this?

[Assistant]
Bed_Levelling.scad:
```
/**
 * Print designed to check that you bed is level
 *
 * print small squares in each corner to ensure even print quality and good adhesion.

 2012-11-15 pgreenland
            Original version

 2023-04-06 PPLLAB
            Allowed for changing the number of rows and columns of squares
            added/moved/changed some comments so that they are visible in the Parameters section
 */

// Define your printers printable area
// If you are using Sprinter firmware then these come directly from configuration.h

//Printable Size X
X_MAX_LENGTH = 220;
//Printable Size Y
Y_MAX_LENGTH = 220;
//Number of rows(along X axis)
Num_rows=4;
//Number of columns(along Y axis)
Num_cols=3;
// REMEMBER ypur layer height must be equal to or less than this otherwise slicing WILL fail
THICKNESS = 0.1; //Square / outline thickness
SIZE = 20; //Square width / height
//Width of border between inner and outer square
GAP = 0.5;
//Width of parameter around square
OUTLINE_WIDTH = 1;
//Offset from limits in each axis
OFFSET = 25;

OSIZE=SIZE + (2 * (GAP + OUTLINE_WIDTH));

for (row=[0:1:Num_rows-1]){
    for (col=[0:1:Num_cols-1]){

        x=(col*(X_MAX_LENGTH-OFFSET*2-(OSIZE*Num_cols))/(Num_cols-1))+(OSIZE*col)+OFFSET;
        y=(row*(Y_MAX_LENGTH-OFFSET*2-(OSIZE*Num_rows))/(Num_rows-1))+(OSIZE*row)+OFFSET;

        translate([x,y,0]) square();
    }
}

 //square();

module square() {
	//Center square
	translate([
				OUTLINE_WIDTH + GAP,
				OUTLINE_WIDTH + GAP,
				0
			])
		cube([SIZE, SIZE, THICKNESS],center=false);

	//Parameter
	difference() {
		//Outer square
		cube([
				OSIZE,
				OSIZE,
				THICKNESS
			],center=false);

		//Inner square
		translate([OUTLINE_WIDTH, OUTLINE_WIDTH, -5])
			cube([SIZE + (2 * GAP), SIZE + (2 * GAP), 10],center=false);
	}
}
```


[User]
Hey, I'm looking to generate some custom vases based on some old Ikea designs. I've got some specific ideas and would love an OpenSCAD script to do it.

Basically, I want to make vases that are a sort of rounded square shape, but the corners can be made sharper or rounder, kind of like the two different Ikea vase designs I've seen. The vases should be able to have variable heights, widths, depths and wall thicknesses. The bottom can have a sort of inset section, which would also be customizable in terms of height and radius. I'd also like the edges, both top and bottom, to have adjustable bevels.

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

*   **Overall Dimensions:**
    *   Outer height
    *   Top outer width
    *   Top outer depth
    *   Wall angle (for how much the walls slope inwards or outwards)
    *   Base thickness (including the lower inset section)
    *   Wall thickness
*   **Top Shape:**
    *   Top outer radius (for rounding the top corners)
*   **Bottom Inset:**
    *   Distance from the projected outer edge to the center of the lower indent's edge
    *   Bottom inner radius
    *   Bottom inner height (set to 0 for no inset)
*   **Edge Details:**
    *   Upper edge bevel radius
    *   Lower edge bevel radius
    *   Inside fillet radius
    * Underside bevel and fillet radius (as a multiple of indent height)

*   **Support Options:**
    *   The ability to generate support structures if needed.  I want to be able to choose between:
        *   No supports
        *   A solid base with a small gap above for adding tape, which is useful for printing on a multi-extruder machine.
        *   Same as the above, but including the vase.
        *   A solid support under the entire vase, useful for multi-extruder printers
        *   Solid support under the base only

    * For the tape-gap support, I'd need to control the vertical gap size.

*   **Output Options:**
    *   A toggle to always render (even when previewing).
    *   A toggle to make the preview transparent.
    *   Curve resolution settings for previews, renders, and small curves (like bevels). There should be a threshold below which a curve is considered small.

I don't need any special libraries. Just the standard OpenSCAD functionality should be fine. Could you create a parametric OpenSCAD file or files that include all of these features? Thanks!

[Assistant]
Ikea_vase.scad:
```
// Ikea inspired vases
// © 2023 Alexander Hajnal
// v1.1
// License: CC BY-NC-SA
// Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International
// https://creativecommons.org/licenses/by-nc-sa/4.0/

// This script is based off of two discontinued Ikea ceramic vases:
//  • One with rounded corners (unknown model)
//  • One with an angular design (000.692.21)

// Be sure to also download the "Ikea_vase.json" file.  It contains presets for the rounded and angular vases as well as additional examples.

// Approximate measurements for rounded vase:
// Height:         120.0
// Inner height:   113.5
// Wall thickness: 5.35
// Top:
// Outer radius:   22.5 (actual curve is more logarithmic than circular; i.e. it bulges out a bit at the centers of the "flat" faces)
// Inner radius:   21.375
// Outer width:    77.45
// Inner width:    66.22
// Bottom:
// Outer width:    66.89
// Middle width:   46.84
// Inner width:    41.37
// Inner radius:   ~10
// Inner height:   ~2
// Edge bevel:
// Lower:          2
// Upper:          1

// Approximate measurements for angular vase (000.692.21):
// Height:         117.5
// Inner height:   112
// Wall thickness: 4.15
// Top:
// Outer radius:   1
// Inner radius:   1 (this script can't generate this given the outer radius)
// Outer width:    73.00
// Inner width:    65.0
// Bottom:
// Outer width:    51.8
// Middle width:   43.6
// Inner width:    37.6
// Inner radius:   ~2
// Inner height:   ~3
// Edge bevel:
// Lower:          1
// Upper:          1

// Version history:

// 1.0 2023-04-08 Initial release
// 1.1 2023-04-09 Minor updates
//     • Fixed typos
//     • Removed dead code
//     • Added additional measurements of prototypes
//     • Added "g" support option (render both gapped support and vase)
//     • Corrected "Square" preset's inner height

/* [ Dimensions ] */

// Outer height
ho = 120.0; // 0.5

// Top outer width
wto = 77.5; // 0.1

// Top outer depth
dto = 77.5; // 0.1

// Wall angle
a = 87.5; // 0.5

// Base thickness (including lower indent)
tb = 7.0; // 0.1

// Wall thickness
tw = 5.35;

// Top outer radius
rto = 22.5; // 0.1

// Distance from projected outer edge to center of lower indent's edge
lbi = 10.5;

// Upper edge bevel radius
bu = 1.0; // 0.1

// Lower edge bevel radius
bl = 2.0; // 0.1

// Inside fillet radius
f = 1.0;

// Bottom inner radius
rbi = 10.0; // 0.1

// Bottom inner height (set to 0 for no indent)
hbi = 2.0; // 0.1

// Underside bevel and fillet radius (as a multiple of indent height)
bfu_ = 1.0; // [ 0.0 : 0.05 : 1.0]
bfu = hbi * bfu_;

/* [ Output options ] */

// Always render (even for preview)
always_render = false;

// Make preview transparent
transparent_preview = false;

// Curve resolution for previews
preview_fn = 32; // 8

// Curve resolution for renders
render_fn = 128; // 8

// Curve resolution for small curves (e.g. bevels)
small_fn = 32; // 8

// Curves with a radius smaller than this are considered small
small_curve_threshold = 2.5; // 0.1

/* [ Supports ] */

// Supports to generate
support_type = "N"; // [ N:None, G:Solid base with tape gaps, g:Solid base with tape gaps along with vase, S:Solid under entire object, B:Solid under base only ]
echo( "support_type: ", support_type );

// Generate support (instead of vase)
generate_support = ( support_type != "N" );

// Generate solid base with tape gaps
tape_gap_support = ( support_type == "G" ) || ( support_type == "g" );

// For above, also generate vase
tape_gap_support_with_vase = ( support_type == "g" );

// Generate solid support under entire object
full_support = ( support_type == "S" );

// Generate solid support under base only
base_support = ( support_type == "B" );

// Gap for tape between support and base of vase.  Located immediately below vase's base.  Pause the print just before printing the vase's bottom and apply masking or kapton tape to the support's top surface.
support_vertical_tape_gap = 0.12; // 0.01

// Computed constants

// Multiples of 8 are used for $fn to keep intersections consistant
// for all typical angles (i.e. multiples of 45°).
$fn = ($preview) ? preview_fn : render_fn;
base_fn = $fn;

// Inner height
//hi = 113.0; // 0.5
hi = ho - (tb + hbi);
echo( "hi: ", hi );

// Top inner width
wti = wto - 2*tw;

// Top inner depth
dti = dto - 2*tw;

// Wall slope
s = tan(a);
echo( "s: ", s );

// Bottom outer width
wbo = wto - 2 * ( ho * 1/s );
echo( "wbo: ", wbo );

// Bottom outer depth
dbo = dto - 2 * ( ho * 1/s );
echo( "dbo: ", dbo );

// Edge path width (to wall's axis of revolution)
wl = wbo - 2*rto;
echo( "wl: ", wl );

// Edge path depth (to wall's axis of revolution)
dl = dbo - 2*rto;
echo( "dl: ", dl );

// Bottom inner width
wbi = wbo - 2*lbi;

// Bottom inner depth
dbi = dbo - 2*lbi;

// Lower to upper outer edge offset (same for both width and depth)
o = wto/2 - wbo/2;
echo( "o: ", o );

// Calling render can cause the final (non-preview) render to fail.
// This module works around that by only calling render when in
// preview mode.
//
// In addition in sets $fn to the preview value not the render
// value; this speeds up processing.  To further speed things up
// an explicit value for $fn can be passed to the module.
module render_fix(local_fn=0) {
  if ($preview) {
    $fn = (local_fn == 0) ? preview_fn : local_fn;
    render() children();
  } else {
    children();
  }
}

// Give block variables local scope
module local() { children(); }

// Not needed since OpenSCAD now supports ^2 notation
//function sqr(x) = pow(x,2);

module skew( xy=0, xz=0, yx=0, zy=0, yz=0, zx=0 ) {
  // For the parameters xy means x is changed as a function of y:
  // skewed_x = child_x + ( child_y * xy )
  // Values passed are units per unit.
  multmatrix( [
                [ 1,  xy, xz, 0 ],
                [ yx, 1,  yz, 0 ],
                [ zx, zy, 1,  0 ],
                [ 0,  0,  0,  1 ]
              ] )
    children();
}

module fillet(w, b, radius, quadrant=0, extend=0) {
  // w → Pair of points defining the wall ("vertical")
  // b → Pair of points defining the base ("horizontal")
  // radius → Fillet's radius
  // quadrant → 0, 1, 2, or 3 → Which of the four quadrants of the line intersection to generate the fillet in
  // extehd → If true then extend flat sides (can be used to ensure objects overlap)

  $fn = ( radius > 0.5 ) ? base_fn : 32;

  // Top inside of wall
  w1 = w[0];
  // Bottom inside of wall
  w2 = w[1];

  // Top of base
  b1 = b[0];
  b2 = b[1];

  // Intersection
  wm = ( w[0].y - w[1].y ) / ( w[0].x - w[1].x );
  wb = w[0].y - wm * w[0].x;
  bm = ( b[0].y - b[1].y ) / ( b[0].x - b[1].x );
  bb = b[0].y - bm * b[0].x;
  intersection = [
                        ( bb - wb ) / ( wm - bm ),
                   wm * ( bb - wb ) / ( wm - bm ) + wb
                 ];

  // Length of wall segment
  lw = sqrt( (w2.x-w1.x)^2 + (w2.y-w1.y)^2 );
  // Unit vector for wall line
  vw = [ (w2.x-w1.x) / lw,
         (w2.y-w1.y) / lw ];

  // Length of base segment
  lb = sqrt( (b2.x-b1.x)^2 + (b2.y-b1.y)^2 );
  // Unit vector for base line
  vb = [ (b2.x-b1.x) / lb,
         (b2.y-b1.y) / lb ];

  // Compute points one radius away perpendicular to the lines

  pw = (quadrant==0 || quadrant==1)
         ? [ w1.x - vw.y * radius,
             w1.y + vw.x * radius ]
         : [ w1.x + vw.y * radius,
             w1.y - vw.x * radius ];
  pb = (quadrant==0 || quadrant==2)
         ? [ b1.x - vb.y * radius,
             b1.y + vb.x * radius ]
         : [ b1.x + vb.y * radius,
             b1.y - vb.x * radius ];

  // Find intersection of the above lines
  // This is the tangent circle's center point
  divisor = vw.x * vb.y - vb.x * vw.y;
  m1 = ( vb.y*(pb.x-pw.x) - vb.x*(pb.y-pw.y) ) / divisor;
  m2 = ( vw.y*(pb.x-pw.x) - vw.x*(pb.y-pw.y) ) / divisor;
  c = [ pw.x + m1 * vw.x,
        pw.y + m1 * vw.y ];

  // Find the circle/line points of tangency
  t1 = [ w1.x + m1 * vw.x, w1.y + m1 * vw.y ];
  t2 = [ b1.x + m2 * vb.x, b1.y + m2 * vb.y ];

  // Draw the fillet

  if (extend) {
    // Extend flat sides

    e = [ extend/m2, extend/m2 ];

    $fn=(radius <= small_curve_threshold ) ? small_fn : $fn;

    difference() {
      polygon( [ t1-e, t1, t2, t2-e, intersection-e ] );
      translate( c )
        circle(radius);
    }

  } else {
    // No extension
    difference() {
      polygon( [ t1, t2, intersection ] );
      translate( c )
        circle(radius);
    }
  }
}

module wall( length, offset ) {
  translate( [ 0, length/2, 0 ] )
    rotate( [ 90, 0, 0 ] )
      linear_extrude(length, convexity=50)
        translate( [ offset/2, 0 ] )
         wall_cross_section();
}

module wall_corner() {
  s=1/tan(a);
  skew(xz=s, yz=s)
    rotate_extrude(angle=90, convexity=50)
      intersection() { // Clip to positive values
        square( [ wto, ho ] );
        skew(xy=-s) {
          wall_cross_section();
        }
      }
}

module wall_cross_section() {
  // Sloped wall

  translate( [ -(wbo/2 - rto), 0, 0 ] ) {
    // Base
    epsilon = 0.1; // Make sure base overlaps side
    polygon( [
               [  wbo/2 - tw + epsilon,  0  ],
               [  wbo/2 - tw  + 1/s*tb + epsilon, tb ],
               [  wbo/2 - rto + 1/s*tb, tb ],
               [  wbo/2 - rto, 0  ]
           ] );

    // Wall (prism with three bevelled corners)
    difference() {
      // Main prism
      polygon( [
                 [  wbo/2 - tw, 0  ],
                 [  wbo/2,      0 ],
                 [  wto/2,      ho ],
                 [  wto/2 - tw, ho ]
             ] );

      // Upper outer bevel
      fillet(w=[ [wbo/2, 0], [wto/2, ho] ], b=[ [0, ho], [wto, ho] ], radius=bu, quadrant=1, extend=0);

      // Upper inner bevel
      fillet(w=[ [wbo/2-tw, 0], [wto/2-tw, ho] ], b=[ [0, ho], [wto, ho] ], radius=bu, quadrant=3, extend=0);

      // Lower outer bevel
      fillet(w=[ [wbo/2, 0], [wto/2, ho] ], b=[ [0, 0], [wbo, 0] ], radius=bu, quadrant=0, extend=0);
    } // END difference: Wall

    // Inner fillet
    fillet(w=[ [wbo/2-tw, 0], [wto/2-tw, ho] ], b=[ [0, tb], [wto, tb] ], radius=bu, quadrant=0, extend=0);
  } // END translate
}

module base_inset_cross_section() {
  // Sloped wall

  difference() {
    // Base
    polygon( [
               [  0,           0  ],
               [  0,           hbi ],
               [  rbi - hbi/2, hbi ],
               [  rbi + hbi/2, 0  ]
           ] );

    // Inner fillet
    fillet(w=[ [ rbi - hbi/2, hbi ], [ rbi + hbi/2, 0 ] ], b=[ [0,hbi], [rbi,hbi] ], radius=bfu, quadrant=3, extend=0);
  }

  // Outer bevel
  fillet(w=[ [ rbi - hbi/2, hbi ], [ rbi + hbi/2, 0 ] ], b=[ [0,0], [rbi,0] ], radius=bfu, quadrant=0, extend=0);
}

module base_inset_edge( length, offset ) {
  // Beveled straight edge for base indent
  translate( [ 0, length/2, 0 ] )
    rotate( [ 90, 0, 0 ] )
      linear_extrude(length, convexity=50)
        translate( [ offset/2-rbi+hbi/2, 0 ] )
         base_inset_cross_section();
}

module base_inset_corner() {
  // Beveled corner for base indent

  rotate_extrude(angle=90, convexity=50)
    base_inset_cross_section();
}

module edge_side_trim_volumes(top, bottom) {
  // Trim either side of each edge to the bevel's edge

  // top: top edge length (wto or dto)
  // bottom: bottom edge length (wbo or dbo)

  rotate( [ 90, 0, 90 ] )
    linear_extrude(top)
      polygon( [
                 [  bottom/2 + top, 0  ],
                 [  bottom/2 - rto, 0  ],
                 [  top/2 - rto,    ho ],
                 [  top/2 + top,    ho ]
               ] );

  mirror( [ 0, 1, 0 ] ) {
    rotate( [ 90, 0, 90 ] )
      linear_extrude(top)
        polygon( [
                   [  bottom/2 + top, 0  ],
                   [  bottom/2 - rto, 0  ],
                   [  top/2 - rto,    ho ],
                   [  top/2 + top,    ho ]
                 ] );
  }
}

module base_trim_volume() {
  points = [
            [  dbo/2-bl,  wbo/2-bl, 0 ],
            [  dbo/2-bl, -wbo/2+bl, 0 ],
            [ -dbo/2+bl, -wbo/2+bl, 0 ],
            [ -dbo/2+bl,  wbo/2-bl, 0 ],

            [  dto/2-bl,  wto/2-bl, ho ],
            [  dto/2-bl, -wto/2+bl, ho ],
            [ -dto/2+bl, -wto/2+bl, ho ],
            [ -dto/2+bl,  wto/2-bl, ho ]
          ];
  faces = [
            [0,1,2,3],  // bottom
            [4,5,1,0],  // front
            [7,6,5,4],  // top
            [5,6,2,1],  // right
            [6,7,3,2],  // back
            [7,4,0,3]   // left
          ];

  hull()
    polyhedron( points, faces );
}

module bottom_indent() {
  offset_w = wbi/2 - rbi + hbi/2;
  offset_d = dbi/2 - rbi + hbi/2;
  union() {
    difference() {
      union() {
        // Straight edges
        base_inset_edge(wbi, dbi);
        rotate( [ 0, 0, 180 ] )
          base_inset_edge(wbi, dbi);
        rotate( [ 0, 0, 90 ] ) {
          base_inset_edge(dbi, wbi);
          rotate( [ 0, 0, 180 ] )
            base_inset_edge(dbi, wbi);
        }
      } // END union: Straight edges

      // Corner trim volumes
      union() {
        translate( [ offset_d, offset_w, -1 ] )
          cube( [ rbi*2, rbi*2, hbi+2 ] );
        rotate( [ 0, 0, 180 ] )
          translate( [ offset_d, offset_w, -1 ] )
            cube( [ rbi*2, rbi*2, hbi+2 ] );
        mirror( [ 1, 0, 0,] ) {
          translate( [ offset_d, offset_w, -1 ] )
            cube( [ rbi*2, rbi*2, hbi+2 ] );
          rotate( [ 0, 0, 180 ] )
            translate( [ offset_d, offset_w, -1 ] )
              cube( [ rbi*2, rbi*2, hbi+2 ] );
        }
      } // END union: Corner trim volumes

    } // End difference (trim inset corners)

    local() {
      offset_w = wbi/2 - rbi + hbi/2;
      offset_d = dbi/2 - rbi + hbi/2;

      // Corners
      translate( [ offset_d, offset_w, 0 ] )
        base_inset_corner();
      rotate( [ 0, 0, 180 ] )
        translate( [ offset_d, offset_w, 0 ] )
          base_inset_corner();
      mirror( [ 1, 0, 0 ] ) {
        translate( [ offset_d, offset_w, 0 ] )
          base_inset_corner();
        rotate( [ 0, 0, 180 ] )
          translate( [ offset_d, offset_w, 0 ] )
            base_inset_corner();
      }
      // END Corners

      // Center
      local() {
        epsilon = 0.0001;
        translate( [ -(offset_d+epsilon), -(offset_w+epsilon), 0 ] )
          cube( [ 2*(offset_d+epsilon), 2*(offset_w+epsilon), hbi ] );
      }
      // END Center

    } // END local

  } // END union
}

module vase() {
  difference() {
    // Main mass
    union() {

      // Box walls and base
      difference(convexity=10) {

        // Box walls (semi-trimmed)
        union() {
          difference() {
            wall(wto-2*rto, dl);
            edge_side_trim_volumes(wto, wbo);
          }

          rotate( [ 0, 0, 180 ] )
            difference() {
              wall(wto-2*rto, dl);
              edge_side_trim_volumes(wto, wbo);
            }

          rotate( [ 0, 0, 90 ] ) {

            difference() {
              wall(dto-2*rto, wl);
              edge_side_trim_volumes(dto, dbo);
            }

            rotate( [ 0, 0, 180 ] )
              difference() {
                wall(dto-2*rto, wl);
                edge_side_trim_volumes(dto, dbo);
              }

          }
        } // END Box walls (semi-trimmed)

        // Corner trim volumes
        union() {
          translate( [ -dl/2, -wl/2, 0 ] )
            skew( xz=1/s, yz=1/s )
              translate( [ dl, wl, -1 ] )
                cube( [ dto, wto, ho+2 ] );
          rotate( [ 0, 0, 180 ] )
            translate( [ -dl/2, -wl/2, 0 ] )
              skew( xz=1/s, yz=1/s )
                translate( [ dl, wl, -1 ] )
                  cube( [ dto, wto, ho+2 ] );
          mirror( [ 1, 0, 0,] ) {
            translate( [ -dl/2, -wl/2, 0 ] )
              skew( xz=1/s, yz=1/s )
                translate( [ dl, wl, -1 ] )
                  cube( [ dto, wto, ho+2 ] );
            rotate( [ 0, 0, 180 ] )
              translate( [ -dl/2, -wl/2, 0 ] )
                skew( xz=1/s, yz=1/s )
                  translate( [ dl, wl, -1 ] )
                    cube( [ dto, wto, ho+2 ] );
          }
        } // END union
        // END Corner trim volumes
      } // End difference (trim wall corners)

      // Corners
      union() {
        translate( [ dl/2, wl/2, 0 ] )
          wall_corner();
        rotate( [ 0, 0, 180 ] )
          translate( [ dl/2, wl/2, 0 ] )
            wall_corner();
        mirror( [ 1, 0, 0 ] ) {
          translate( [ dl/2, wl/2, 0 ] )
            wall_corner();
          rotate( [ 0, 0, 180 ] )
            translate( [ dl/2, wl/2, 0 ] )
              wall_corner();
        }
      } // END union: Corners

      // Base
      intersection() {
        local() {
          // The padding here covers up the gap on the inside of the edge's base.
          pad = tb * (1/s);
          translate( [ -(dl+2*pad)/2, -(wl+2*pad)/2, 0 ] )
            cube( [ (dl+2*pad), (wl+2*pad), tb ] );
        }
        base_trim_volume();
      } // END difference: Base

    } // END union: Main mass

    // Bottom indent
    if ( hbi > 0 ) {
      bottom_indent();
    }

  } // END difference
}

module volume() {
  points = [
            [  wbo/2,  wbo/2, 0 ],
            [  wbo/2, -wbo/2, 0 ],
            [ -wbo/2, -wbo/2, 0 ],
            [ -wbo/2,  wbo/2, 0 ],

            [  wto/2,  wto/2, ho ],
            [  wto/2, -wto/2, ho ],
            [ -wto/2, -wto/2, ho ],
            [ -wto/2,  wto/2, ho ]
          ];
  faces = [
            [0,1,2,3],  // bottom
            [4,5,1,0],  // front
            [7,6,5,4],  // top
            [5,6,2,1],  // right
            [6,7,3,2],  // back
            [7,4,0,3]   // left
          ];

  polyhedron( points, faces );
}

module optional_transparency() {
  if ( transparent_preview && $preview ) {
    %children();
  } else {
    children();
  }
}

module optional_always_render() {
  if ( always_render ) {
    render_fix()
      children();
  } else {
    children();
  }
}

//!render() wall_cross_section();
//!wall_cross_section();
//!wall_corner();
//!wall(wto-2*rto);
//%volume();

//!base_inset_cross_section();
//!base_inset_corner();
//!base_inset_edge(wto-2*rto);

optional_transparency()
optional_always_render()
if ( generate_support ) {
  // Generate support

  if ( tape_gap_support ) {
    if ( hbi > 0 ) {
      // Generate solid base with tape gap
      linear_extrude( hbi-support_vertical_tape_gap )
        projection()
          intersection() {
            bottom_indent();
            translate( [ -dto/2, -wto/2, hbi-0.00001 ] )
              cube( [ dto, wto, ho ] );
          }
    } else {
      echo("No support needed");
    }

    if ( tape_gap_support_with_vase ) {
      vase();
    }

  } else if ( full_support ) {
    // Generate solid support under entire object
    if ( hbi > 0 ) {
      bottom_indent();
    }
    difference() {
      linear_extrude(ho)
        projection()
          vase();
        render_fix()
          union() {
            translate( [ -dto/2, -wto/2, -ho ] )
              cube( [ dto, wto, ho ] );
            translate( [ -dto/2, -wto/2, ho - tw*0.001 ] )
              cube( [ dto, wto, ho ] );
            hull()
              vase();
          }
    }

  } else if ( base_support ) {
    if ( hbi > 0 ) {
      // Generate solid support under base only
      bottom_indent();
    } else {
      echo("No support needed");
    }

  }

} else {
  // Generate vase
  vase();
}

```


[User]
I'm looking to design a customizable holder for SSDs and M.2 drives, and I'd like to do it parametrically in OpenSCAD. I have some existing code, but I think it's best to start fresh and do it properly.

Essentially, I need a holder that can stack multiple SSDs or M.2 drives, with each "slot" being adjustable in dimensions. I want to define the number of slots, and the spacing between them. It needs to be able to handle standard 2.5 inch SSDs, as well as some common external SSDs like Samsung's T5 and T7 series, M.2 drives in various sizes, and a custom size for unusual drives if needed. A key feature is to make the height of each slot variable, so I can choose how deep each layer is, and therefore how tall the whole holder ends up being. Also, it would be nice if the holder is angled at the top. Finally, a parameter to create double-wide holders would be nice.

Here's a breakdown of the features I need:

*   **Slot Count:** A parameter to specify the number of slots/layers.
*   **SSD Type:** A parameter to select between standard 2.5" SSD, Samsung T5, Samsung T7, a custom SSD dimension option, and various M.2 drive sizes (22x30, 22x80, 22x110, 16x20).
*   **Custom Dimensions:** When "Custom SSD" type is selected, the option to specify custom height, width, and thickness.
*   **Slot Dimensions:** Ability to add some clearance around the chosen drive dimensions.
*  **Slot Depth/Height:** A parameter that lets me set the depth or height of each slot (the vertical separation between each layer), and also a separate depth parameter that specifies the depth of each slot.
*   **Double Width:** An option to create a holder that's two slots wide.
*   **Wall Thickness:** Parameters for inner and outer wall thickness.
*   **Angled Top:** The top of the holder should have an angled cut.
*   **Show SSD:** (Optional) Ability to render the SSD dimensions to help see how they will fit, and to help visualize the slot size during development.

I'd prefer that you don't use any external libraries, like BOSL or similar, but stick with pure OpenSCAD primitives.

[Assistant]
SSDHolder3.scad:
```

  //-----------------//
 // SSD Holder V2.0 //
//-----------------//

// This program is Public Domain 2023

// * Use the OpenScad customizer

// SSD Dimensions employed
// Normal = 100 x 74 x 9
// SamSung_T5 = 74 x 57.3 x 10.5 mm
// SamSung_t7 = 85 x 57 x 8 mm

Show_SSD = false;
Double   = false;

/* [Holder Body] */

Inner_Wall   = 2;   // [1.6:.4:3.2]
Outer_Wall   = 3;   // [1.6:.4:4]
Clearance    = 0.3; // [0:.1:2]
Slot_Count   = 8;   // [1:20]

SSD = 0;            // [0:Normal,1:Samsun_S5,2:Samsung_S7,3:Unknown,4:Custom,5:M.2-16x20,6:M.2-22x30,7:M.2-22x80,8:M.2-22x110]

Slot_Depth   = 20;  // [5:.01:20]
Slot_Z_Step  = 5;   // [2:.01:20]

/* [Custom SSD Size] */

Custom_Height = 76;  // [40:150]
Custom_Width  = 57;  // [20:100]
Custom_Thick  = 10;  // [3:.1:25]

echo(Custom_Thick);

if (Double) { One(); translate([0,Outer_Wall]) mirror([0,1]) One(); }
else { One(); }

module One() {
if (SSD == 0) Holder();
if (SSD == 1) Holder(10.5+1,74+1,57+1);
if (SSD == 2) Holder(8+1,85+1,57+1);
if (SSD == 3) Holder(10.9+1,62.3+1,76.1+1);
if (SSD == 4) Holder(Custom_Thick,Custom_Width,Custom_Height);
if (SSD == 5) Holder(2,17,20);
if (SSD == 6) Holder(3,23,30);
if (SSD == 7) Holder(3,23,80);
if (SSD == 8) Holder(4,23,110);
}

//---------------------
// Generate SSD Holder
//
module Holder(SlotW = 9,SlotL=74,CHeight=100) {
SlotW = SlotW+Clearance;
SlotL = SlotL+Clearance;

//Slope_Factor = 5;

Height = Slot_Count*Slot_Z_Step+Outer_Wall+Slot_Depth/2;

Interior_x = Slot_Count*(SlotW) + (Slot_Count-1) * Inner_Wall;

   difference() {
      // Base structure
      cube([Interior_x+Outer_Wall*2,SlotL+Outer_Wall*2,Height]);

      Inset = .5;
      translate([-.01,Outer_Wall])
      rotate([0,-90])
         mirror([0,0,-1])
      linear_extrude(Inset,scale = [1-Inset/Slot_Depth,1])
      square([Slot_Depth,SlotL]);

      // Remove slots
      for (x=[0:Slot_Count-1]) {
         translate([x*(SlotW+Inner_Wall)+Outer_Wall,Outer_Wall,x*Slot_Z_Step])
         cube([SlotW,SlotL,CHeight]);
      }

      // Hollow interior
      translate([Outer_Wall,Outer_Wall+10])
      cube([Interior_x,SlotL-20,CHeight+500]);

      Slice_Angle = atan(Slot_Z_Step/(SlotW+Inner_Wall));
      echo(Slice_Angle,(SlotW+Inner_Wall));
      // Angle top
      translate([0,-1,Slot_Depth+Outer_Wall])
      rotate([0,-Slice_Angle])
      cube([700,200,200]);

   }

   // Add Bottom
   translate([0,0,-Outer_Wall+.01])
   cube([Interior_x+Outer_Wall*2,SlotL+Outer_Wall*2,Outer_Wall]);

   // Show Carts
   if (Show_SSD && $preview)
   color("aqua")
   for (x=[floor(Slot_Count/2):Slot_Count-1]) {
      translate([x*(SlotW+Inner_Wall)+Outer_Wall+Clearance/2,Outer_Wall+Clearance/2,x*Slot_Z_Step])
      cube([SlotW-Clearance,SlotL-Clearance,CHeight]);
   }
}
```


[User]
Hey, I'm looking to design a parametric wedding ring in OpenSCAD. I've got some specific measurements and a quirky little calculation to throw in.

Essentially, it's a ring with a comfort fit profile and some decorative spiraling extrusions around the outer edge. I want to be able to customize the ring size (using US ring sizing), the ring width, and this weird "cartonic divergence factor".

For the ring size, I'm thinking it should use the standard US ring size scale which goes from about size 2 up to 16, in increments of 0.25. The ring width should also be adjustable, somewhere between 2mm and 9mm and adjustable by 0.12mm increments. Finally the cartonic divergence factor is really just a random constant that I would like to be able to set between 0.37 and 0.42.

The ring profile isn't just a flat cylinder. It has more of a rounded or "comfort fit" type profile. I've got a function I've been using as a starting point for this.

```
module ring(size,width){
$fn=120;

width2=width+0.20;
mmr=((size*.8128+11.635)/2)+0.75;
echo((mmr-0.75)*2);
difference(){
translate([0,0,width/2])
rotate_extrude()
translate([mmr,0])
union(){
difference(){
scale([1.25/width2*2,1])
circle(r=width2/2);
translate([-2,width2/-2])
square([2,width2]);
}
scale([0.75/width2*2,1])
circle(r=width2/2);
}
translate([0,0,-1])
cylinder(r=mmr+2,h=1);
translate([0,0,width])
cylinder(r=mmr+2,h=1);

for(i=[0:29])
rotate([0,0,12*i])
linear_extrude(height=width,twist=24)
translate([mmr+1.25,0])
circle(r=0.4,$fn=4);

for(i=[0:29])
rotate([0,0,12*i])
linear_extrude(height=width,twist=-24)
translate([mmr+1.25,0])
circle(r=0.4,$fn=4);

}
}
```
I don't need this exact code, but I'm providing it as a starting point for the overall idea. I do want those decorative twists on the outside.

I'd like the code to be as readable as possible, so any comments would be appreciated.  Thanks!

[Assistant]
wedding_ring_2.scad:
```
US_ring_size=10.75;//[2:0.25:16]
width_mm=6.00;//[2.04:0.12:9]
cartonic_divergence_factor=0.37;//[0.37:0.01:0.42]

ring(US_ring_size,width_mm);

module ring(size,width){
$fn=120;

width2=width+0.20;
mmr=((size*.8128+11.635)/2)+0.75;
echo((mmr-0.75)*2);
difference(){
translate([0,0,width/2])
rotate_extrude()
translate([mmr,0])
union(){
difference(){
scale([1.25/width2*2,1])
circle(r=width2/2);
translate([-2,width2/-2])
square([2,width2]);
}
scale([0.75/width2*2,1])
circle(r=width2/2);
}
translate([0,0,-1])
cylinder(r=mmr+2,h=1);
translate([0,0,width])
cylinder(r=mmr+2,h=1);

for(i=[0:29])
rotate([0,0,12*i])
linear_extrude(height=width,twist=24)
translate([mmr+1.25,0])
circle(r=0.4,$fn=4);

for(i=[0:29])
rotate([0,0,12*i])
linear_extrude(height=width,twist=-24)
translate([mmr+1.25,0])
circle(r=0.4,$fn=4);

}
}

```