[User]
Hey, I'm looking to create a customizable origami-style whale design in OpenSCAD, similar to the one I found on Thingiverse (thing:2734803). I need it to be parametric so I can adjust things like the overall size, the thickness of the lines, and the height.

Specifically, I need the following parameters:

*   **`max_size_in_millimeter`**: This will determine the maximum size of the longest side of the whale. The other side should scale proportionally. I'd like to be able to set this anywhere between 20 and 300mm.
*   **`model_height_in_millimeter`**: The height/thickness of the model itself, which should range from 0.2mm to 100mm.
*   **`outline_size_in_millimeter`**: The thickness of the outer border of the whale, which I'd like to be able to adjust from 0.5mm to 20mm.
*   **`inline_size_in_millimeter`**: The thickness of the inner lines within the whale. The range should be from 0.5mm to 20mm as well.
*   **`inline_edge_radius_in_millimeter`**: I need to control the roundness of the ends of the inner lines, from 0 to 5mm radius.
*   **`flip_model`**: A simple "yes" or "no" option to flip the model horizontally.

The whale outline itself should be based on these points, using a polygon, and the inner lines are also polygons that cut into the outline:

**Outer Points:**

```
A1 = [870, 680];
A2 = [1298, 628];
A3 = [1458, 679];
A4 = [1575, 779];
A5 = [1658, 737];
A6 = [1722, 666];
A7 = [1839, 648];
A8 = [1796, 720];
A9 = [1931, 771];
A10 = [1796, 780];
A11 = [1764, 774];
A12 = [1670, 864];
A13 = [1307, 916];
A14 = [1301, 1009];
A15 = [1262, 1023];
A16 = [1188, 918];
A17 = [1009, 933];
A18 = [880, 817];
```

**Inner Points:**

```
B1 = [1046, 820];
B2 = [1005, 789];
B3 = [1108, 792];
B4 = [1308, 844];
B5 = [1139, 846];
B6 = [1126, 825];
```

**Inner Polygons (to cut out):**

```
C1 = [A1, B2, A2];
C2 = [B2, A2, B4, B3, B1];
C3 = [B1, B3, B6];
C4 = [B3, B4, B5, B6];
C5 = [A1, B2, B1, B6, B5, A16, A17, A18]; // Don't render this one; it's only mentioned in the source as a comment and is incomplete
C6 = [B5, B4, A13, A14, A15, A16];
C7 = [A2, A3, A4, A12, A13, B4];
C8 = [A4, A5, A11, A12];
C9 = [A5, A6, A7, A8];
C10 = [A5, A8, A9, A10, A11];
```

The design should use `linear_extrude` with a `difference()` to create the whale shape. `offset()` should be used to create the outer and inner lines.

Could you generate the necessary OpenSCAD code for this, please? I don't need any extra libraries. Thanks!

[Assistant]
customizable_origami_whale.scad:
```
/*
 * Customizable Origami - Whale - https://www.thingiverse.com/thing:2734803
 * by Dennis Hofmann - https://www.thingiverse.com/mightynozzle/about
 * created 2017-12-28
 * version v1.0
 *
 * Changelog
 * --------------
 * v1.0:
 *      - final design
 * --------------
 *
 * This work is licensed under the Creative Commons - Attribution - NonCommercial - ShareAlike license.
 * https://creativecommons.org/licenses/by-nc-sa/3.0/
 */

 // Parameter Section //
//-------------------//

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

// The maximum size of the longest side. The shorter side will be automatically resized in same ratio.
max_size_in_millimeter = 120; //[20:300]

// The height of the model.
model_height_in_millimeter = 5; //[0.2:0.2:100]

// Thickness of the outer outline.
outline_size_in_millimeter = 1.4; //[0.5:0.1:20]

// Thickness of the inner outline.
inline_size_in_millimeter = 0.7; //[0.5:0.1:20]

// Roundiness of the ends of the inner outlines.
inline_edge_radius_in_millimeter = 0.6; //[0.0:0.1:5]

// Flip model
flip_model = "no"; //[yes,no]

/*[hidden]*/
max_size = max_size_in_millimeter;
model_height = model_height_in_millimeter;
$fn=32;

// Outer Points
A1 = [870, 680];
A2 = [1298, 628];
A3 = [1458, 679];
A4 = [1575, 779];
A5 = [1658, 737];
A6 = [1722, 666];
A7 = [1839, 648];
A8 = [1796, 720];
A9 = [1931, 771];
A10 = [1796, 780];
A11 = [1764, 774];
A12 = [1670, 864];
A13 = [1307, 916];
A14 = [1301, 1009];
A15 = [1262, 1023];
A16 = [1188, 918];
A17 = [1009, 933];
A18 = [880, 817];

outline = [A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17, A18];

// Inner Points
B1 = [1046, 820];
B2 = [1005, 789];
B3 = [1108, 792];
B4 = [1308, 844];
B5 = [1139, 846];
B6 = [1126, 825];

// Polygons
C1 = [A1, B2, A2];
C2 = [B2, A2, B4, B3, B1];
C3 = [B1, B3, B6];
C4 = [B3, B4, B5, B6];
C5 = [A1, B2, B1, B6, B5, A16, A17, A18];
C6 = [B5, B4, A13, A14, A15, A16];
C7 = [A2, A3, A4, A12, A13, B4];
C8 = [A4, A5, A11, A12];
C9 = [A5, A6, A7, A8];
C10 = [A5, A8, A9, A10, A11];

cut_polygons = [C1, C2, C3, C4, /*C5,*/ C6, C7, C8, C9, C10];

min_x = A1[0];
min_y = A2[1];
max_x = A9[0];
max_y = A15[1];

x_size = max_x - min_x;
y_size = max_y - min_y;

x_factor = max_size / x_size;
y_factor = max_size / y_size;

inline_size = x_size > y_size ? inline_size_in_millimeter / x_factor / 2: inline_size_in_millimeter / y_factor / 2;
inline_edge_radius = x_size > y_size ? inline_edge_radius_in_millimeter / x_factor: inline_edge_radius_in_millimeter / y_factor;
outline_size = x_size > y_size ? outline_size_in_millimeter / x_factor - inline_size: outline_size_in_millimeter / y_factor - inline_size;

 // Program Section //
//-----------------//

if(x_size > y_size) {
    resize(newsize=[max_size, x_factor * y_size, model_height]){
        if(flip_model == "yes") {
            mirror([0,1,0]) {
                rotate([180,180,0]) {
                    create(outline, cut_polygons);
                }
            }
        } else {
            create(outline, cut_polygons);
        }
    }
} else {
    resize(newsize=[y_factor * x_size, max_size, model_height]){
        if(flip_model == "yes") {
            mirror([0,1,0]) {
                rotate([180,180,0]) {
                    create(outline, cut_polygons);
                }
            }
        } else {
            create(outline, cut_polygons);
        }
    }
}

 // Module Section //
//----------------//

module create() {
    linear_extrude(height=1) {
        difference() {
            offset(r = -0) {
                offset(r = +outline_size) {
                    polygon(points = outline, convexity = 10);
                }
            }

            for(cut_polygon = [0:len(cut_polygons)]) {
                offset(r = +inline_edge_radius) {
                    offset(r = -inline_size - inline_edge_radius) {
                        polygon(points = cut_polygons[cut_polygon], convexity = 10);
                    }
                }
            }
        }
    }
}

```


[User]
I need a drill guide for making stacked Lack tables. I'm planning to use dowels to connect the tabletops and legs, rather than printing a bunch of brackets. The dowels will be glued in place. I already have a version that works, but it's very basic and I think it could be more robust and easier to use. It's mostly just a simple square with a pilot hole.

Here's what I'm looking for:

1.  **Parametric Design:** The guide needs to be fully parametric, so I can adjust for different leg sizes and material thicknesses. I'd like to control:
    *   `leg_size`: The side length of the square legs, and also the size of the square cutout in the guide itself.
    *   `pilot_hole_diameter`: The diameter of the pilot hole for marking the drill location.
    *   `guide_thickness`: The thickness of the main guide base.
    *   `guide_height`: The height of the guide walls surrounding the main piece.
    *   `wall_thickness`: The thickness of the guide walls. This should be independent of the `guide_thickness`
    *   `hole_offset`: Optionally, an offset value from center to move the pilot hole if we don't want it perfectly centered in the leg.

2.  **Guide Walls:**  Instead of the simple strips on two sides that my current version has, the new design should have a full guide wall around all four sides of the leg cutout. This will make it easier to align and hold in place.

3.  **Flush Mounting:** The guide walls should be a separate body from the main square base. This way, I can print the guide on its side and have a flat, flush bottom so that it sits flat on the table top or leg surface.

4.  **Clear Marking:** The pilot hole should be just that, a small hole that allows me to mark my drilling location. I don't need it to be a full through hole.

5.  **OpenSCAD Libraries:** Please use the BOSL2 library for this project. I'm pretty familiar with it and it should make this easier to do.

So, to reiterate, I need a parameterized drill guide that lets me accurately mark holes on the center of Lack table legs and tops, with easy to print features. I'd like to be able to specify the size of the leg/cutout, the pilot hole diameter, the thickness of the guide base, the height of the guide walls, their wall thickness, and optionally an offset. I need a design where the walls are separate, and the bottom is flat.

Let me know what you come up with!

[Assistant]
lack-template.scad:
```
$fn=128+0;

// Diameter of pilot hole (mm)
pilot_hole_diameter=3;
// Square leg size (mm)
leg_size=50.5;
half_leg=leg_size/2;
// Thickness of jig (mm)
thick=2;
// Height of guide part (mm)
guide_height=12;

union() {

difference() {
translate([-half_leg,-half_leg,0]) cube([leg_size,leg_size,thick]);
translate([0,0,0]) cylinder(d=pilot_hole_diameter,h=thick*2.5,center=true);
}

translate([-half_leg-thick,-half_leg-thick,0]) cube([thick,leg_size+thick,guide_height]);
translate([-half_leg,-half_leg-thick,0]) cube([leg_size,thick,guide_height]);
}
```


[User]
I need a pool ball marker, like the one described in the provided example, but I need it to be parametric and work well for different ball sizes. I'd like to be able to adjust the ball diameter using a variable at the beginning of the file.

The basic idea is a rectangular prism with a cutout that partially cradles a sphere. This will allow it to sit snug against a ball. I want the main body of the marker to be a cube that is half the ball diameter in height. I want it to have a width and depth equal to the full ball diameter, so it's like a cube that's been squashed in Z. The cutout should be a sphere that's half the ball diameter in radius. The center of the sphere should be on the top face of the cube, and should extend down into the cube such that half of the sphere's diameter is outside of the cube and the other half is inside of the cube. Also, the cutout sphere's center should be aligned with the center of the marker along the X axis, and the Y axis should be offset to create a proper "cradle" that prevents the marker from sliding off a ball. I think a Y-offset of 1/5th of the ball diameter for the sphere should work well.

Could you generate the necessary OpenSCAD file to achieve this? I'd like it to be easy to adjust the ball diameter as a parameter. No external libraries are required, the built in OpenSCAD primitives should suffice.

[Assistant]
pool-ball-marker.scad:
```
$fs = 1/1;
$fa = 1/1;

ballDiameter = 57.2;

difference() {
	translate([-ballDiameter/2, 0, 0]) {
		cube([ballDiameter, ballDiameter/2, ballDiameter/3]);
	}
	translate([0, -ballDiameter/5, ballDiameter/2]) {
		sphere(ballDiameter/2);
	}
}

```


[User]
I'm looking to generate a customizable 2D giraffe design using OpenSCAD. I'd like to control the overall size of the giraffe, the height (thickness) of the model, and the thickness of both the outer and inner outlines. It's important that the design uses polygons for the shapes and has rounded corners for the inner outlines. I also need the option to flip the model horizontally.

The base of the design is already in the provided code, with specific point coordinates (A1 through A14) defining the outer shape and polygons (C1 through C6) that should be cut out to create the inner outline. The scaling of the outline and inner line thicknesses needs to be relative to the largest dimension of the design.

Could you generate an OpenSCAD file that allows these customizations? I need to be able to adjust the following:

*   `max_size_in_millimeter`:  The maximum size of the longest side of the giraffe. The other side should scale proportionally to maintain the aspect ratio.
*   `model_height_in_millimeter`: The overall height/thickness of the model.
*   `outline_size_in_millimeter`: The thickness of the outer outline.
*   `inline_size_in_millimeter`: The thickness of the inner outlines.
*   `inline_edge_radius_in_millimeter`: The radius of the rounded edges on the inner outlines.
*  `flip_model`: An option to flip the model horizontally ("yes" or "no").

The file should use the provided point coordinates (A1-A14) and cut polygons (C1-C6). No special libraries are needed for this project.

[Assistant]
customizable_origami_giraffe.scad:
```
/*
 * Customizable Origami - Giraffe - https://www.thingiverse.com/thing:2735802
 * by Dennis Hofmann - https://www.thingiverse.com/mightynozzle/about
 * created 2017-12-28
 * version v1.0
 *
 * Changelog
 * --------------
 * v1.0:
 *      - final design
 * --------------
 *
 * This work is licensed under the Creative Commons - Attribution - NonCommercial - ShareAlike license.
 * https://creativecommons.org/licenses/by-nc-sa/3.0/
 */

 // Parameter Section //
//-------------------//

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

// The maximum size of the longest side. The shorter side will be automatically resized in same ratio.
max_size_in_millimeter = 120; //[20:300]

// The height of the model.
model_height_in_millimeter = 5; //[0.2:0.2:100]

// Thickness of the outer outline.
outline_size_in_millimeter = 1.6; //[0.5:0.1:20]

// Thickness of the inner outline.
inline_size_in_millimeter = 0.8; //[0.5:0.1:20]

// Roundiness of the ends of the inner outlines.
inline_edge_radius_in_millimeter = 0.4; //[0.0:0.1:5]

// Flip model
flip_model = "no"; //[yes,no]

/*[hidden]*/
max_size = max_size_in_millimeter;
model_height = model_height_in_millimeter;
$fn=32;

// Outer Points
A1 = [393, 329];
A2 = [530, 214];
A3 = [622, 297];
A4 = [724, 1012];
A5 = [1008, 1106];
A6 = [1006, 1230];
A7 = [1074, 1253];
A8 = [1006, 1198];
A9 = [1007, 1650];
A10 = [796, 1391];
A11 = [591, 1650];
A12 = [571, 1181];
A13 = [535, 323];
A14 = [399, 366];

outline = [A1, A2, A3, A4, A5, A7, A8, A9, A10, A11, A12, A13, A14];

// Polygons
C1 = [A1, A2, A13, A14];
C2 = [A2, A3, A4, A12, A13];
C3 = [A4, A5, A10, A12];
C4 = [A5, A6, A8, A9, A10];
C5 = [A10, A12, A11];
C6 = [A5, A7, A8];

cut_polygons = [C1, C2, C3, C4, C5, C6];

min_x = A1[0];
min_y = A2[1];
max_x = A7[0];
max_y = A11[1];

x_size = max_x - min_x;
y_size = max_y - min_y;

x_factor = max_size / x_size;
y_factor = max_size / y_size;

inline_size = x_size > y_size ? inline_size_in_millimeter / x_factor / 2: inline_size_in_millimeter / y_factor / 2;
inline_edge_radius = x_size > y_size ? inline_edge_radius_in_millimeter / x_factor: inline_edge_radius_in_millimeter / y_factor;
outline_size = x_size > y_size ? outline_size_in_millimeter / x_factor - inline_size: outline_size_in_millimeter / y_factor - inline_size;

 // Program Section //
//-----------------//

if(x_size > y_size) {
    resize(newsize=[max_size, x_factor * y_size, model_height]){
        if(flip_model == "yes") {
            mirror([0,1,0]) {
                rotate([180,180,0]) {
                    create(outline, cut_polygons);
                }
            }
        } else {
            create(outline, cut_polygons);
        }
    }
} else {
    resize(newsize=[y_factor * x_size, max_size, model_height]){
        if(flip_model == "yes") {
            mirror([0,1,0]) {
                rotate([180,180,0]) {
                    create(outline, cut_polygons);
                }
            }
        } else {
            create(outline, cut_polygons);
        }
    }
}

 // Module Section //
//----------------//

module create() {
    linear_extrude(height=1) {
        difference() {
            offset(r = -0) {
                offset(r = +outline_size) {
                    polygon(points = outline, convexity = 10);
                }
            }

            for(cut_polygon = [0:len(cut_polygons)]) {
                offset(r = +inline_edge_radius) {
                    offset(r = -inline_size - inline_edge_radius) {
                        polygon(points = cut_polygons[cut_polygon], convexity = 10);
                    }
                }
            }
        }
    }
}

```


[User]
Hey, I'm looking to create a customizable origami shark design in OpenSCAD, similar to the one I found on Thingiverse, but I'd like it to be completely parametric and generated from scratch.

The main idea is a 2D shark outline with inner cutouts, designed to be laser-cut or 3D printed. I'd need to control things like:

*   **Overall Size:** The longest side of the shark should be adjustable using a `max_size` parameter, with the shorter side scaling proportionally.
*   **Thickness:** I'll need to set the `model_height` to control the overall thickness of the model for 3D printing purposes.
*   **Outline Thicknesses:** I need to control the `outline_size` and `inline_size` parameters separately to define the main outline thickness and the thickness of the inner cut lines.
*   **Inner Outline Roundness:**  I need `inline_edge_radius` so the corners of the cut lines will be rounded to prevent sharp edges.
*   **Mirroring:** There should be a boolean parameter (`flip_model`) to mirror the design on the Y-axis.

I'm providing the original coordinates and polygon definitions for the basic shark outline and cut lines:

**Outer Points:**

```
A1 = [205, 429];
A2 = [660, 443];
A3 = [777, 448];
A4 = [1107, 153];
A5 = [1082, 476];
A6 = [1351, 617];
A7 = [1751, 436];
A8 = [1512, 677];
A9 = [1639, 813];
A10 = [1393, 722];
A11 = [1011, 788];
A12 = [839, 776];
A13 = [848, 798];
A14 = [675, 964];
A15 = [678, 789];
A16 = [540, 767];
```
**Inner Points:**
```
B1 = [1481, 708];
```

**Polygons:**

```
C1 = [A3, A4, A5];
C2 = [A1, A2, A12, A13, A15, A16];
C3 = [A15, A14, A13];
C4 = [A2, A3, A5, A6, B1, A10, A11, A12];
C5 = [A6, A7, A8, B1];
C6 = [A8, A9, A10, B1];
```
The design should be generated using linear extrusion of a 2D shape. The main shape should use an offset polygon based on the outline points. The inner cut lines should be generated using offset polygons based on the defined cut polygons, and then subtracted from the main shape.

I don't need any special libraries, I think a basic OpenSCAD script should be enough. Can you provide the SCAD code for this?

[Assistant]
customizable_origami_shark.scad:
```
/*
 * Customizable Origami - Shark - https://www.thingiverse.com/thing:2736967
 * by Dennis Hofmann - https://www.thingiverse.com/mightynozzle/about
 * created 2017-12-29
 * version v1.0
 *
 * Changelog
 * --------------
 * v1.0:
 *      - final design
 * --------------
 *
 * This work is licensed under the Creative Commons - Attribution - NonCommercial - ShareAlike license.
 * https://creativecommons.org/licenses/by-nc-sa/3.0/
 */

 // Parameter Section //
//-------------------//

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

// The maximum size of the longest side. The shorter side will be automatically resized in same ratio.
max_size_in_millimeter = 120; //[20:300]

// The height of the model.
model_height_in_millimeter = 5; //[0.2:0.2:100]

// Thickness of the outer outline.
outline_size_in_millimeter = 1.8; //[0.5:0.1:20]

// Thickness of the inner outline.
inline_size_in_millimeter = 0.9; //[0.5:0.1:20]

// Roundiness of the ends of the inner outlines.
inline_edge_radius_in_millimeter = 0.9; //[0.0:0.1:5]

// Flip model
flip_model = "no"; //[yes,no]

/*[hidden]*/
max_size = max_size_in_millimeter;
model_height = model_height_in_millimeter;
$fn=32;

// Outer Points
A1 = [205, 429];
A2 = [660, 443];
A3 = [777, 448];
A4 = [1107, 153];
A5 = [1082, 476];
A6 = [1351, 617];
A7 = [1751, 436];
A8 = [1512, 677];
A9 = [1639, 813];
A10 = [1393, 722];
A11 = [1011, 788];
A12 = [839, 776];
A13 = [848, 798];
A14 = [675, 964];
A15 = [678, 789];
A16 = [540, 767];

outline = [A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16];

// Inner Points
B1 = [1481, 708];

// Polygons
C1 = [A3, A4, A5];
C2 = [A1, A2, A12, A13, A15, A16];
C3 = [A15, A14, A13];
C4 = [A2, A3, A5, A6, B1, A10, A11, A12];
C5 = [A6, A7, A8, B1];
C6 = [A8, A9, A10, B1];

cut_polygons = [C1, C2, C3, C4, C5, C6];

min_x = A1[0];
min_y = A4[1];
max_x = A7[0];
max_y = A14[1];

x_size = max_x - min_x;
y_size = max_y - min_y;

x_factor = max_size / x_size;
y_factor = max_size / y_size;

inline_size = x_size > y_size ? inline_size_in_millimeter / x_factor / 2: inline_size_in_millimeter / y_factor / 2;
inline_edge_radius = x_size > y_size ? inline_edge_radius_in_millimeter / x_factor: inline_edge_radius_in_millimeter / y_factor;
outline_size = x_size > y_size ? outline_size_in_millimeter / x_factor - inline_size: outline_size_in_millimeter / y_factor - inline_size;

 // Program Section //
//-----------------//

if(x_size > y_size) {
    resize(newsize=[max_size, x_factor * y_size, model_height]){
        if(flip_model == "yes") {
            mirror([0,1,0]) {
                rotate([180,180,0]) {
                    create(outline, cut_polygons);
                }
            }
        } else {
            create(outline, cut_polygons);
        }
    }
} else {
    resize(newsize=[y_factor * x_size, max_size, model_height]){
        if(flip_model == "yes") {
            mirror([0,1,0]) {
                rotate([180,180,0]) {
                    create(outline, cut_polygons);
                }
            }
        } else {
            create(outline, cut_polygons);
        }
    }
}

 // Module Section //
//----------------//

module create() {
    linear_extrude(height=1) {
        difference() {
            offset(r = -0) {
                offset(r = +outline_size) {
                    polygon(points = outline, convexity = 10);
                }
            }

            for(cut_polygon = [0:len(cut_polygons)]) {
                offset(r = +inline_edge_radius) {
                    offset(r = -inline_size - inline_edge_radius) {
                        polygon(points = cut_polygons[cut_polygon], convexity = 10);
                    }
                }
            }
        }
    }
}

```


[User]
I'm looking for an OpenSCAD design for a customizable card caddy for board games. I'd like it to be parametric, so I can easily adjust it for different card sizes and numbers of card stacks.

Here are the key features I need:

*   **Adjustable Card Dimensions:** I need to be able to specify the width and height of the cards I'm using. The design should automatically calculate the well size based on these dimensions, adding a small buffer space around the card.
*   **Variable Number of Wells:** I'd like to be able to set the number of card wells in the caddy.
*   **Adjustable Well Depth:** The depth of the card wells should be configurable to accommodate different numbers of cards.
*   **Border and Padding:** I'll need to be able to specify the width of the border around the entire caddy, as well as the padding space between individual card wells.
*   **Well Shelf:** A shelf or lip around the bottom of each well to keep the cards from sliding out is important. I need to be able to adjust the depth and width of this lip. It would be great if it was possible to make a solid shelf.
*   **Finger Cutouts:** I want finger cutouts along the front of the wells to make it easier to grab the cards. These cutouts should be able to be fine-tuned in terms of size and vertical/horizontal position.
*   **Clearance:** I'd like to be able to specify the card buffer spacing - basically a small amount of space around the cards inside the wells.

It seems like it would be pretty straightforward to generate the basic caddy with a series of cube subtractions, but I'm not sure the best way to implement the finger cutouts or the beveling. For the beveling, I don't need anything fancy; just a 45-degree angle going into the well.

I'm open to suggestions on the best way to structure the OpenSCAD code to make it easy to use and modify. I'd prefer to avoid any additional libraries if possible, just using the standard OpenSCAD language. Could you generate the .scad file for this?

[Assistant]
Customizable_Board_Game_Card_Caddy.scad:
```
// All measurements are in millimeters.

/* [Parameters] */

// The width of a card. We'll add buffer space later, so measure this as accurately as possible.
card_width = 44;

// The height of a card. We'll add buffer space later, so measure this as accurately as possible.
card_height = 68;

// The number of card wells.
number_of_wells = 3; // [1:6]

// The depth of the wells. 25 cards fit nicely per 10mm.
well_depth = 10;

/* [Tweaks] */

// The width of the border material around the edge of the caddy.
caddy_border_width = 5;

// The empty buffer space to leave around a card in a well.
card_well_buffer_spacing = 1; // [1.0: loose, 0.5: tight]

// The space between adjacent cards. (I.e., the width of the divider between cells plus double
// the card well buffer spacing.) The default value calculated here will result in a divider
// width that's equal to the outside caddy_border_width width. If this caddy is to be placed
// over existing markings on a board, it can be overridden with an explicit value. Must be a
// minimum of 1 + (card_well_buffer_spacing * 2).
card_padding = caddy_border_width + (card_well_buffer_spacing * 2);

// The well shelf is the edge around the bottom of the well that keeps the cards from falling out. This parameter controls its depth.
well_shelf_depth = 1;

// This parameter controls the well shelf width. Set it to a really big value if you want a solid shelf.
well_shelf_width = 3;

// The size of the finger cutout.
filger_cutout_size = 15;

// Used to finely tweak the finger cutout front/back location.
filger_cutout_y_tweak = 0;

// Used to finely tweak the finger cutout up/down location.
filger_cutout_z_tweak = well_shelf_depth;

// The height of the card wells.
card_well_height = card_height + (card_well_buffer_spacing * 2);

// The width of the card wells.
card_well_width = card_width + (card_well_buffer_spacing * 2);

// The space between card wells.
card_well_padding = card_padding - (card_well_buffer_spacing * 2);

// Resolution.
$fn = 100 * 1;

// preview[view:north east, tilt:top diagonal]

difference() {

  // base brick
  cube([
    (card_well_width * number_of_wells) + (card_well_padding * (number_of_wells - 1)) + (caddy_border_width * 2),
    card_well_height + (caddy_border_width * 2) + well_depth,
    well_depth + well_shelf_depth
  ]);

  for (i = [0 : number_of_wells - 1]) {

    x = (i * (card_well_width + card_well_padding)) + caddy_border_width;
    y = caddy_border_width + well_depth;

    // card well
    translate([x, y, well_shelf_depth]) {
      cube([card_well_width, card_well_height, well_depth + 1]);
    }

    // card well shelf
    translate([x + well_shelf_width, y + well_shelf_width, -well_shelf_width]) {
      cube([
        card_well_width - (2 * well_shelf_width),
        card_well_height - (2 * well_shelf_width),
        well_depth + well_shelf_depth + 1
      ]);
    }

    // bevel
    translate([x, y, well_shelf_depth]) {
      rotate([45, 0, 0]) {
        cube([card_well_width, well_depth, well_depth * 2]);
      }
    }

    // finger cutout
    translate([
      x + (card_well_width / 2),
      filger_cutout_size + filger_cutout_y_tweak,
      filger_cutout_size + filger_cutout_z_tweak
    ]) {
      sphere(filger_cutout_size);
    }

  }

}
```


[User]
Hey, I'm looking to get a parametric design for a miniature chair in OpenSCAD. I've got some specific dimensions and a basic structure in mind that I'd like to be able to adjust, and I'm hoping you can help me put it together.

The chair should have a back, a seat, and four legs. The back will be slightly angled, and the overall shape should be kind of rounded with some interesting curves. I've got specific parameters for the dimensions, so here they are.

For the chair back:
*   I need to set the overall height of the back.
*   There should be separate settings for the thickness at the top and bottom of the back.
*   I need to set the width of the bottom of the back.
*   I want a handhold cutout, so I need to control it's width and height.
*   And finally, I need to be able to control the angle of the back from vertical.

For the seat:
*   I want to set the thickness of the seat.
*   I need to set the depth of the seat.
*   And I need to set the width of the front of the seat.

For the legs:
*   I need to set the overall height of the legs.
*   I want to be able to control an offset from the edges of the seat and back where the legs are positioned.
*   I need to set the thickness at the top, middle, and bottom of the legs.

I would like to be able to adjust all of those parameters. I am hoping to keep this to one .scad file if that is possible. I'm not using any special libraries for this project, so this can just use standard OpenSCAD functions. Thanks for the help!

[Assistant]
chair-build.scad:
```
back();
seat();
legs();
/* [Hidden] */

/* [Chair Back] */
//Chair Back Height (mm)
chair_back_height = 30;
//Chair Back Top Thickness (mm)
chair_back_top_thickness = 3;
//Chair Back Bottom Thickness (mm)
chair_back_bottom_thickness = 2;
//Chair Back Bottom Width (mm)
chair_back_bottom_width = 35;
//Hand Hold Width (mm)
chair_back_handhold_width = 6;
//Hand Hold Height (mm)
chair_back_handhold_height = 1;
//Chair Angel
chair_back_angle = 10;

/* [Chair Seat] */
//Chair Seat Thickness (mm)
chair_seat_thickness = 3;
//Chair Seat Depth (mm)
chair_seat_depth = 40;
//Chair Seat Front Width (mm)
chair_seat_front_width = 50;

/* [Chair Legs] */
//Leg Height (mm)
leg_height = 40;
//Leg Edge Offset
leg_edge_offset = 3;
//Leg Top Thickness (mm)
leg_top_thickness = 2.5;
//Leg Middle Thickness (mm)
leg_middle_thickness = 2.5;
//Leg Bottom Thickness (mm)
leg_bottom_thickness = 1.5;
module legs() {
    translate([chair_back_bottom_width/2-leg_edge_offset,leg_edge_offset,0]) {
        leg();
    }

    translate([-chair_back_bottom_width/2+leg_edge_offset,leg_edge_offset,0]) {
        leg();
    }

    translate([chair_seat_front_width/2-leg_edge_offset,chair_seat_depth-leg_edge_offset,0]) {
        leg();
    }

    translate([-chair_seat_front_width/2+leg_edge_offset,chair_seat_depth-leg_edge_offset,0]) {
        leg();
    }
}
module back() {

    rotate([chair_back_angle,0,0]) {
    translate([0,0,chair_back_height]) {
    rotate([90,0,0]) {
    difference() {
        hull() {
            scale([1.5,1,1]){
                intersection() {
                    rotate_extrude(convexity=10, $fn=50) {
                        translate([20,0,0]) {
                            circle(chair_back_top_thickness, $fn=50);
                        }
                    }
                    translate([0,40,0]){
                        rotate([0,0,30]){
                            linear_extrude(height=40, center=true) {
                                circle(50, $fn=3);
                            }
                        }
                    }
                }
            }

            translate([0,-chair_back_height,0]){
                rotate([0,90,0]){
                    linear_extrude(height=chair_back_bottom_width, center=true) {
                        circle(chair_back_bottom_thickness, $fn=50);
                    }
                }
            }
        }

        //hand hold
        hull() {
            translate([0,12,-10]){
                hull(){
                    translate([chair_back_handhold_width,0,0]){
                        sphere(chair_back_handhold_height, $fn=50);
                    }
                    translate([-chair_back_handhold_width,0,0]){
                        sphere(chair_back_handhold_height, $fn=50);
                    }
                }
            }

            translate([0,12,10]){
                hull(){
                    translate([3,0,0]){
                        sphere(3, $fn=50);
                    }
                    translate([-3,0,0]){
                        sphere(3, $fn=50);
                    }
                }
            }
        }
    }
    }
    }
    }
}
module leg() {
    hull() {
        cylinder(1, leg_top_thickness, leg_top_thickness, false);
        translate([0,0,-leg_height/2]) {
            sphere(leg_middle_thickness, $fn=50 );
        }
        translate([0,0,-leg_height]) {
            cylinder(1, leg_bottom_thickness, leg_bottom_thickness, false);
        }
    }
}
module seat() {
    hull() {
        translate([chair_back_bottom_width/2 - (chair_seat_thickness/2),0,0]){
            sphere(chair_seat_thickness, false, $fn=50);
        }
        translate([-chair_back_bottom_width/2 + (chair_seat_thickness/2),0,0]){
            sphere(chair_seat_thickness, false, $fn=50);
        }

        translate([chair_seat_front_width/2,chair_seat_depth,0]){
            sphere(chair_seat_thickness, false, $fn=50);
        }
        translate([-chair_seat_front_width/2,chair_seat_depth,0]){
            sphere(chair_seat_thickness, false, $fn=50);
        }
    }
}

```


[User]
I need a custom pegboard insert for those double ring holders, like the ones you see for pegboard hooks. I'm trying to make them actually useful! I've got an existing design, but I'd like something more flexible. I want the insert to fit snugly within the double rings and then have a cylindrical hole in the middle to hold whatever tool I want.

Here are the key things I need:

*   **A main cylinder body:** This is what fits inside the pegboard rings. I need to be able to adjust its outer diameter.
*   **A lip:** At the bottom of the insert, there should be a lip that rests on the bottom ring of the pegboard holder. I need to control the diameter and thickness of this lip.
*   **A center hole:** A cylindrical hole goes all the way through the insert to hold whatever tool, and I need to be able to control its diameter.
*   **Retaining spheres:** At the very top of the insert, there should be four small spheres to keep it from falling out of the double ring pegboard holder. Their radius should be adjustable.
*   **Everything needs to be parametric:** I need to easily adjust the different measurements, like the diameters, thickness, and height. It needs to be well-commented so that I know what's what.
*   **Facets:** I need to control the number of facets used when creating the cylinders and the spheres, so that the user can control the level of roundness/smoothness.

Basically, I need to be able to enter the following:

*   **`outer_diameter`**:  The diameter of the main cylinder that goes into the double rings.
*   **`inner_diameter`**: The diameter of the center hole.
*   **`height`**: The height of the main cylinder (not including the lip or spheres).
*   **`lip_diameter`**: The diameter of the lip at the bottom.
*   **`lip_thickness`**: The thickness of the lip at the bottom.
*   **`sphere_radius`**: The radius of the small spheres at the top.
*  **`facets`**: How many facets used for making the cylinders and spheres.

Could you generate an OpenSCAD file that does all of this? I don't have any specific libraries in mind, so just use the most appropriate ones.

[Assistant]
Pegboard_Double_Ring_Insert_V2.scad:
```
// what is inner diameter of the rings?
outer_diameter = 18.5;

// how big is the hole ion the center?
inner_diameter = 12;

// distance between the top and botton of the rings on the outside
height = 43 ;

// diameter of the lip that will overhang the ring
lip_diameter = 25;

// how thick the overhanging lip should be
lip_thickness = 2;

// radius of the retaining spheres that keep the tube in place
sphere_radius = 0.5;

// total height of the tube including the lip
total_height = lip_thickness + height;

// how round do you want it?
facets = 100;

//Let's built it!
Insert(inner_diameter);

// I just learned how to do this so lets create a function
module Insert(Size)
{
    // subtract the hole from the body
    difference()
    {
        //create the body

        union()
        {
            //main cylinder
            translate([0,0,lip_thickness]) cylinder(h=height,d=outer_diameter,$fn=facets);

            //lip
            cylinder(h=lip_thickness,d=lip_diameter,$fn=facets);

            //retaining spheres
            translate([outer_diameter/2,0,total_height]) sphere(sphere_radius, $fn=facets);
            translate([-outer_diameter/2,0,total_height]) sphere(sphere_radius, $fn=facets);
            translate([0,outer_diameter/2,total_height]) sphere(sphere_radius, $fn=facets);
            translate([0,-outer_diameter/2,total_height]) sphere(sphere_radius, $fn=facets);
        }

        //cut the hole
        cylinder(h=total_height, d=Size,$fn=facets);
    }
}

```


[User]
Okay, I need a parametric OpenSCAD design for servo arms, and I want it to be pretty flexible. I've seen some existing implementations, but I want a clean one from the ground up, based on how I think about the problem.

Here's the basic idea: The core of the design is a servo spline connection, with one or more arms extending from it. The spline needs to be customizable for various servo types, and the arms need to have adjustable length and count. I’d like it to be easily expanded for new spline types as they are needed.

Specifically, I need to be able to specify:

*   **Spline Type:** I'd like to support at least the following spline types, and I need it to be really easy to add new ones as needed without needing to rewrite the entire program. The dimensions for these are defined in the existing file I'm referencing, and I'll copy these as a guide:
    *   Hitec C1-24T
    *   Hitec D1-15T
    *   Futaba 1F-15
    *   Futaba 2F-21T
    *   Futaba 3F-25T
     * Actobotics Horn (Hitec) - This one is a bit different, it's a horn, so it just has 8 mounting holes at the outer diameter.
     * Actobotics Horn (Futaba) - Same as above, but with the Futaba spline.
     * Tetrix Horn (Hitec) - Same as Actobotics, but the screw hole pattern is a bit different.
     * Tetrix Horn (Futaba) - Same as the above, but with a Futaba spline.
*   **Arm Length:** The length of the arm, measured from the center of the spline to the center of the hole at the end of the arm.
*   **Arm Count:** The number of arms extending from the center. These should be evenly spaced around the spline.
*  **Arm Screw Diameter**: The diameter of the screw hole at the end of each arm.
*   **Base Thickness:** The thickness of the base of the spline.
*   **Servo Head Clearance:** This is how much space I want between the servo head and the base of the arm, to avoid the two parts grinding together.

The generated model should have the following features:

*   A proper spline connection for the servo type. The spline parameters should be specified in an array.
*   One or more arms extending from the spline, and the arms should look good, probably having a basic hull shape.
*   A screw hole at the end of each arm and a hole through the center of the spline.
*   The option to generate just the spline or the whole arm, including the spline base.
* When the Actobotics or Tetrix horns are selected, I want the screw holes to be in the specified locations, not at the end of an arm shape.

I'm not requesting any specific external libraries, so please write all code from scratch.

[Assistant]
servo_arm_RF.scad:
```
/**
    Parametric servo arm generator for OpenScad

    Forked from 2012 Charles Rincheval.  All rights reserved.

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
    License as published by the Free Software Foundation; either
    version 2.1 of the License, or (at your option) any later version.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public
    License along with this library; if not, write to the Free Software
    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA

*/

// Which Spline would you like to see?
// spline_type = 1; // [1:"Hitec C1-24T",2:"Hitec D1-15T",3:"Futaba 1F-15",4:"Futaba 2F-21T (9g?)",5:"Futaba 3F-25T]";
// Spline Size
spline_type = 1; // [1:Hitec C1-24T, 2:Hitec D1-15T, 3:Futaba 1F-15, 4:Futaba 2F-21T (9g?), 5:Futaba 3F-25T, 6:Actobotics Horn(Hitec), 7:Actobotics Horn(Futaba), 8:Tetrix Horn(Hitec), 9:Tetrix Horn(Futaba) ]

arm_length = 20;

arm_count = 1; // [1,2,3,4,5,6,7,8]

arm_screw_diameter = 2.0;

base_thickness = 2.0;

/**
    Clear between arm head and servo head
    With PLA material, use clear : 0.3, for ABS, use 0.2
*/
SERVO_HEAD_CLEARANCE = 0.2;

$fn = 40/1;

/**
    Head / Tooth parameters
    http://https://www.servocity.com/servo-spline-info

    First array (head related) :
    0. Head external diameter  (INTERNAL OF TEETH)
    1. Head height
    2. Head thickness
    3. Head screw diameter
    4. Head Base Thickness

    Second array (tooth related) :
    0. Tooth count
    1. Tooth height
    2. Tooth length
    3. Tooth width
*/
/**
   Tooth (ON SERVO)

     |<-w->|
     |_____|___
     /     \  ^h
   _/       \_v
    |<--l-->|

   - tooth height (h)
   - tooth length (l)
   - tooth width (w)

    For a new servo: Seems to work best to first set the tooth height to zero,
     and get the outer diameter snug, then work on the teeth.

   Printed very well on Printrbot Simple Pro  0.3mm nozzle, 0.1 layer PLA

   If you need just the spline, set the arm length, and head base thickness to zero

*/
//------------------------------------------------

HITEC_D1_SPLINE = [
                    [7.6, 5.5, 1.8, 3.4, base_thickness],
                    [15, 0.7, 1.3, 0.2]
                  ];
module servo_hitec_d1(length, count) {
  servo_arm(HITEC_D1_SPLINE, [length, count]);
}
//------------------------------------------------

HITEC_C1_SPLINE = [
                    [5.6, 3.5, 1.6, 2.8, base_thickness],
                    [24, 0.4, 0.7, 0.051]
                  ];
module servo_hitec_c1(length, count) {
  servo_arm(HITEC_C1_SPLINE, [length, count]);
}
//------------------------------------------------

FUTABA_1F_SPLINE = [
                     [4.0, 3.75, 1.1, 2.3, base_thickness],
                     [15, 0.25, 0.6, 0.09]
                   ];
module servo_futaba_1f(length, count) {
    servo_arm(FUTABA_1F_SPLINE, [length, count]);
}
//------------------------------------------------

FUTABA_2F_SPLINE = [
                     [4.90, 3, 1.8, 2.3, base_thickness],
                     [21, 0.57, 0.7, 0.1]
                   ];
module servo_futaba_2f(length, count) {
  servo_arm(FUTABA_2F_SPLINE, [length, count]);
}
//------------------------------------------------

FUTABA_3F_SPLINE = [
                     [5.92, 3, 1.1, 2.5, base_thickness],
                     [25, 0.3, 0.7, 0.1]
                   ];
module servo_futaba_3f(length, count) {
  servo_arm(FUTABA_3F_SPLINE, [length, count]);
}
//------------------------------------------------

/**
    If you want to support a new servo, juste add a new spline definition array
    and a module named like servo_XXX_YYY where XXX is servo brand and YYY is the
    connection type (3f) or the servo type (s3003)
*/

//    Servo head

module servo_head(params, clear = SERVO_HEAD_CLEARANCE) {

  head = params[0];
  tooth = params[1];

  head_diameter = head[0];
  head_height = head[1];
  head_base = head[4];

  tooth_count = tooth[0];
  tooth_height = tooth[1];
  tooth_length = tooth[2];
  tooth_width = tooth[3];

  //     %cylinder(r = (head_diameter / 2), h = head_height + 1);

  cylinder(r = head_diameter / 2 - tooth_height + 0.03 + clear, h = head_height);

// add teeth
    for (i = [0 : tooth_count]) {
      rotate([0, 0, i * (360 / tooth_count)]) {
        translate([0, head_diameter / 2 - tooth_height + clear, 0]) {
          servo_head_tooth(tooth_length, tooth_width, tooth_height, head_height);
        }
      }
    }
  }

module servo_head_tooth(length, width, height, head_height){

  curvatureAdd = 0.05;
  linear_extrude(height = head_height) {
    polygon([[-length / 2 - curvatureAdd, -curvatureAdd], [-width / 2, height], [width / 2, height], [length / 2 + curvatureAdd, -curvatureAdd]]);
   }
}
/**
    Servo hold
    - Head / Tooth parameters
    - Arms params (length and count)
*/
module servo_arm(params, arms) {

  head = params[0];
  tooth = params[1];

  head_diameter = head[0];
  head_height = head[1];
  head_thickness = head[2];
  head_screw_diameter = head[3];
  head_base = head[4];

  tooth_length = tooth[2];
  tooth_width = tooth[3];

  arm_length = arms[0];
  arm_count = arms[1];

  /**
      Servo arm
      - length is from center to last hole
  */
  module arm(tooth_length, tooth_width, head_height, hole_count ) {

//    arm_screw_diameter = 2;

    difference() {
      union() {
        hull() {
          cylinder(r = tooth_width / 2, h = head_base);
          translate([0, tooth_length, 0]) {
          cylinder(r = arm_screw_diameter / 2 + 1.5, h = head_base);
//          #cylinder(r = tooth_width / 3, h = head_base);

          }
        }

      }

      // Hole
//      for (i = [0 : hole_count - 1]) {
        //translate([0, length - (length / hole_count * i), -1]) {
        translate([0, tooth_length , -1]) {
          cylinder(r = arm_screw_diameter / 2, h = 10);
        }
//      }

      translate([0, 0, -0.001])cylinder(r = head_screw_diameter / 2, h = 10);
    }

  }

  arm_thickness = head_thickness;

  // Arm
  difference() {   // spline hub
    union(){
      for (j = [0 : arm_count - 1]) {
        rotate([0, 0, j * (360 / arm_count)]) {
          arm(arm_length, head_diameter + arm_thickness * 2, head_height, 1);
            hull() {                  // cross support
              translate([0 , head_diameter/2, 0])
              cylinder(r = head_base / 2, h = head_base + head_height);
              translate([0 , max(arm_length - 4,0), 0])
              cylinder(r = head_base / 2, h = head_base);
            }
         }
       }

       cylinder(r = head_diameter / 2 + head_thickness, h = head_height + head_base );
     }

     translate([0, 0, -0.001])
     cylinder(r = head_screw_diameter / 2, h = 10);  // hole
     translate([0, 0, head_base + 0.0001])
     servo_head(params); // teeth

  }

     if (spline_type >= 6 ){       // servo horns for actobotics,tetrix
         difference(){
              rad=13.5;
              if (spline_type >= 8) {
                  cylinder(r=11.5,h=head_base);}
              else {
                  cylinder(r=13.5,h=head_base);}

                 for (j = [0 : arm_count - 1]) {
                     rotate([0, 0, j * (360 / arm_count)])
                     translate([0, arm_length , -1])
                     cylinder(r = 2.05 , h = 10);
//                     cylinder(r = arm_screw_diameter / 2 , h = 10);
                         }

         }
         }

}

print_part();

module print_part() {
	if (spline_type == 1)  {
		servo_hitec_c1 (arm_length, arm_count);
	} else if (spline_type  == 2) {
		servo_hitec_d1 (arm_length, arm_count);
	} else if (spline_type  == 3)  {
		servo_futaba_1f(arm_length, arm_count);
	} else if (spline_type  == 4) {
		servo_futaba_2f(arm_length, arm_count);
	} else if (spline_type  == 5) {
		servo_futaba_3f(arm_length, arm_count);
	} else if (spline_type  == 6) {
		servo_hitec_c1 (0.770*25.4/2, 8);
	} else if (spline_type  == 7) {
		servo_futaba_3f(0.770*25.4/2, 8);
	} else if (spline_type  == 8) {
		servo_hitec_c1 (16/2, 8);
	} else if (spline_type  == 9) {
		servo_futaba_3f(16/2, 8);
	}
}
/*
translate([00,0,0]) servo_futaba_1f(10, 1);
translate([10,0,0]) servo_futaba_2f(10, 1);
translate([0,-30,0]) servo_futaba_3f(20, 4);
translate([20,0,0]) servo_hitec_c1 (30, 1);
translate([32,0,0]) servo_hitec_d1 (40, 2);
*/

```


[User]
I'm looking for a way to generate 2D origami-style designs, specifically of a meerkat, that I can then 3D print or laser cut. I want to be able to customize the size, height, and thickness of the outlines. I've found an example online that seems perfect - it uses OpenSCAD and is called "customizable_origami_meerkat.scad."

I want the design to be parametric so I can easily adjust these settings.  I need to be able to control:

*   **Maximum Size:** The overall size of the design, specifying the longest dimension in millimeters (the other dimension will scale proportionally).
*   **Model Height:** The thickness or height of the 3D model, also in millimeters.
*   **Outer Outline Thickness:** The thickness of the outer border of the meerkat.
*   **Inner Outline Thickness:** The thickness of the lines creating the internal details of the meerkat.
*   **Inner Outline Edge Roundness:** How rounded the ends of the inner lines should be.

Also, it would be great to have an option to flip the design horizontally.

The design should consist of a single, flat shape made up of outlines and inner cutouts/engravings, essentially using a difference operation in OpenSCAD to remove areas within the outer outline and leaving the inner lines as extrusions.  The points defining the shape are given as cartesian coordinates.

Could you create the OpenSCAD code for me, or point me towards any libraries that can help with this?  I haven't found anything that already does this kind of origami generation. I do not have any preference for any particular library, but MCAD seems like it might have some useful functions if there is not already an existing library.

[Assistant]
customizable_origami_meerkat.scad:
```
/*
 * Customizable Origami - Meerkat - https://www.thingiverse.com/thing:2738092
 * by Dennis Hofmann - https://www.thingiverse.com/mightynozzle/about
 * created 2017-12-30
 * version v1.0
 *
 * Changelog
 * --------------
 * v1.0:
 *      - final design
 * --------------
 *
 * This work is licensed under the Creative Commons - Attribution - NonCommercial - ShareAlike license.
 * https://creativecommons.org/licenses/by-nc-sa/3.0/
 */

 // Parameter Section //
//-------------------//

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

// The maximum size of the longest side. The shorter side will be automatically resized in same ratio.
max_size_in_millimeter = 120; //[20:300]

// The height of the model.
model_height_in_millimeter = 5; //[0.2:0.2:100]

// Thickness of the outer outline.
outline_size_in_millimeter = 1.6; //[0.5:0.1:20]

// Thickness of the inner outline.
inline_size_in_millimeter = 0.8; //[0.5:0.1:20]

// Roundiness of the ends of the inner outlines.
inline_edge_radius_in_millimeter = 0.4; //[0.0:0.1:5]

// Flip model
flip_model = "no"; //[yes,no]

/*[hidden]*/
max_size = max_size_in_millimeter;
model_height = model_height_in_millimeter;
$fn=32;

// Outer Points
A1 = [688, 424];
A2 = [738, 407];
A3 = [897, 310];
A4 = [1022, 320];
A5 = [1043, 350];
A6 = [1064, 482];
A7 = [1087, 657];
A8 = [1113, 784];
A9 = [1122, 963];
A10 = [1205, 1146];
A11 = [1268, 1449];
A12 = [1323, 1551];
A13 = [1367, 1597];
A14 = [1540, 1593];
A15 = [1358, 1641];
A16 = [1217, 1545];
A17 = [1110, 1358];
A18 = [1093, 1390];
A19 = [1087, 1515];
A20 = [1048, 1641];
A21 = [848, 1641];
A22 = [1023, 1579];
A23 = [927, 1222];
A24 = [853, 1103];
A25 = [876, 982];
A26 = [843, 998];
A27 = [846, 1018];
A28 = [797, 1061];
A29 = [811, 1008];
A30 = [835, 962];
A31 = [931, 822];
A32 = [867, 709];
A33 = [921, 564];
A34 = [922, 510];
A35 = [861, 508];
A36 = [830, 491];
A37 = [740, 473];
A38 = [692, 445];

outline = [A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17, A18, A19, A20, A21, A22, A23, A24, A25, A26, A27, A28, A29, A30, A31, A32, A33, A34, A35, A36, A37, A38];

// Inner Points
B1 = [1017, 524];
B2 = [848, 459];
B3 = [973, 684];
B4 = [1036, 901];
B5 = [959, 960];
B6 = [921, 963];
B7 = [965, 1170];
B8 = [1188, 1341];

// Polygons
C1 = [A1, A2, A37, A38];
C2 = [A2, A3, A4, B2, A37];
C3 = [A37, B2, A35, A36];
C4 = [A4, A5, A6, B2];
C5 = [B2, A35, A34, B1, A6];
C6 = [A6, A7, B1];
C7 = [B1, B3, A7];
C8 = [B1, A33, A34];
C9 = [B1, B3, A33];
C10 = [A33, A32];
C11 = [A7, A8, B4, A32, B3];
C12 = [A33, B3, A32];
C13 = [B4, A9, A8];
C14 = [A32, B4, B5, B6, A30, A31];
C15 = [A30, A29, A26, A25, B6];
C16 = [A29, A28, A27, A26];
C17 = [A24, A25, B6, B5, B4, A9];
C18 = [A24, A9, A10];
C19 = [A24, A23, B7, A10];
C20 = [B7, A10, A17, A18];
C21 = [B7, A18, A19, A20, A22, A23];
C22 = [A22, A20, A21];
C23 = [A10, A11, A16, A17];
C24 = [A11, A16, A15, A13, A12];
C25 = [A13, A15, A14];

cut_polygons = [/*C1,*/ C2, C3, C4, C5, C6, C7, C8, C9, C10, C11, C12, C13, C14, C15, C16, C17, C18, C19, C20, C21, C22, C23, C24, C25];

min_x = A1[0];
min_y = A3[1];
max_x = A14[0];
max_y = A21[1];

x_size = max_x - min_x;
y_size = max_y - min_y;

x_factor = max_size / x_size;
y_factor = max_size / y_size;

inline_size = x_size > y_size ? inline_size_in_millimeter / x_factor / 2: inline_size_in_millimeter / y_factor / 2;
inline_edge_radius = x_size > y_size ? inline_edge_radius_in_millimeter / x_factor: inline_edge_radius_in_millimeter / y_factor;
outline_size = x_size > y_size ? outline_size_in_millimeter / x_factor - inline_size: outline_size_in_millimeter / y_factor - inline_size;

 // Program Section //
//-----------------//

if(x_size > y_size) {
    resize(newsize=[max_size, x_factor * y_size, model_height]){
        if(flip_model == "yes") {
            mirror([0,1,0]) {
                rotate([180,180,0]) {
                    create(outline, cut_polygons);
                }
            }
        } else {
            create(outline, cut_polygons);
        }
    }
} else {
    resize(newsize=[y_factor * x_size, max_size, model_height]){
        if(flip_model == "yes") {
            mirror([0,1,0]) {
                rotate([180,180,0]) {
                    create(outline, cut_polygons);
                }
            }
        } else {
            create(outline, cut_polygons);
        }
    }
}

 // Module Section //
//----------------//

module create() {
    linear_extrude(height=1) {
        difference() {
            offset(r = -0) {
                offset(r = +outline_size) {
                    polygon(points = outline, convexity = 10);
                }
            }

            for(cut_polygon = [0:len(cut_polygons)]) {
                offset(r = +inline_edge_radius) {
                    offset(r = -inline_size - inline_edge_radius) {
                        polygon(points = cut_polygons[cut_polygon], convexity = 10);
                    }
                }
            }
        }
    }
}

```


[User]
Hey, I'm looking for a design for a wall mount to hang my RC cars by their tires. I'd like it to be parametric so I can adjust the size for different cars.

Here are the things I need to be adjustable:

*   **Wheel Diameter:** Obviously the diameter of the tire, which will determine the size of the curved part. I'm thinking a range of 25mm to 180mm should cover most of my needs.
*   **Width:** The width of the hanger itself.  I'm guessing a range of 15mm to 120mm for that.
*   **Mount Hole Diameter:** The diameter of the screw holes.
*   **Mount Hole Inset Diameter:** The diameter of the inset (counterbore) to accept screw heads.
*   **Mount Hole Count:** I want the option of either one or three mounting holes.
*   **Part:** I need to be able to generate a single left part, a single right part (mirrored), or both.

I'm thinking the main part should be a curved shape to hold the tire, with a flat area where the screws will go.  I need to be able to print it without any support material, so it probably needs to be mostly flat on the wall side. I also want a small lip on the bottom to make sure the tire doesn't easily slip off, like a small raised edge.

Could you generate the OpenSCAD files for this? I'm not sure if you'd need one file or multiple, but if you could make it so that everything is configurable with parameters, that would be great! It doesn't need to be any specific version of OpenSCAD either.

[Assistant]
car-hangers.scad:
```

// Summit 1/16 wheel size: 103mm
// WLToys A979 wheel size: 71mm
// ERevo 1/16 wheel size: 82mm

// preview[view:north west, tilt:top diagonal]
// Wheel diameter
wheel_diameter = 100; // [25:180]

// Width of the hanger
width = 20; // [15:120]

// Diameter of the mount holes
hole_diameter = 4;

// Diameter of the mount hole insets
hole_inset_diameter = 8.4;

// Mount hole count
hole_count = "three"; // [one: One, three:Three]

// Which one would you like to see?
part = "left"; // [left:Left only,right:Right only,both:Left and right]

/* [Hidden] */
wheel_radius = wheel_diameter / 2;
outer_radius = wheel_radius + 2;
_t = 3;
_screw_head_radius = hole_inset_diameter/2;
_screw_hole_radius = hole_diameter/2;
_w = width;

// translate([0,0,-_w/2]) %cylinder(r=wheel_radius,_w*2);

if (part == "left") {
    tire_holder();
} else if (part == "right") {
    mirror([0,1,0])
    tire_holder();
} else if (part == "both") {
    //translate([wheel_diameter/2,0,0]) rotate([0,0,-70])
    translate([0,wheel_diameter/2+10,0]) tire_holder();
    translate([0,-wheel_diameter/2-10,0]) mirror([0,1,0]) tire_holder();
}

module tire_holder() {

    $fn=100;
    difference() {
        union() {
            translate([-(outer_radius+_t),-(outer_radius+_t)-_t,0])
                cube([(outer_radius+_t)*2,_t*2,_w]);
            /*
            translate([-(outer_radius+_t),-(outer_radius+_t),0])
                cube([(outer_radius+_t)*2,(outer_radius+_t),_t]);
            */
            difference() {
                union() {
                    // Main holder "clamp"
                    cylinder(r=outer_radius+_t,_w);
                    // Printable edge to improve rigidity of the clamp
                    translate([0,0,_w-4])
                        cylinder(r1=outer_radius+_t,r2=outer_radius+_t+2,4);
                    // Bottom edge for improved adhesion and rigidity
                    cylinder(r1=outer_radius+_t+2,r2=outer_radius+_t,4);

                    translate([-(outer_radius+_t),-(outer_radius+_t),0])
                        cube([(outer_radius+_t)*2,(outer_radius+_t),_t]);
                }
                translate([0,0,-1]) cylinder(r=outer_radius,_w+2);
                rotate([0,0,30+0.2*wheel_diameter])
                    translate([0,0,-1])
                    cube([(outer_radius+_t)*3,(outer_radius+_t)*3,_w*4]);
                rotate([0,0,30])
                    translate([-(outer_radius+_t)*3,0,-1])
                    cube([(outer_radius+_t)*3,(outer_radius+_t)*3,_w*4]);
            }
        }

        translate([0,0,_w/2])
        rotate([90,0,0]) {
            if (hole_count == "three") {
                translate([(outer_radius+_t)/2,0,0]) cylinder(r=_screw_hole_radius,h=(outer_radius+_t)*2);
                translate([(outer_radius+_t)/2,0,0]) cylinder(r=_screw_head_radius,h=(outer_radius+_t)-_t);
                translate([-(outer_radius+_t)/2,0,0]) cylinder(r=_screw_hole_radius,h=(outer_radius+_t)*2);
                translate([-(outer_radius+_t)/2,0,0]) cylinder(r=_screw_head_radius,h=(outer_radius+_t)-_t);
                translate([0,0,0]) cylinder(r=_screw_hole_radius,h=(outer_radius+_t)*2);
                translate([0,0,2]) cylinder(r=_screw_head_radius,h=(outer_radius+_t)-_t);
            } else if (hole_count == "one") {
                translate([0,0,0]) cylinder(r=_screw_hole_radius,h=(outer_radius+_t)*2);
                translate([0,0,2]) cylinder(r=_screw_head_radius,h=(outer_radius+_t)-_t);
            }

        }
    }

}

/*
difference() {
    resize([0,0,(outer_radius+_t)*3]) {
        difference() {
            sphere(r=outer_radius+_t,$fn=50);
            sphere(r=outer_radius,$fn=50);
        }
    }
    translate([-(outer_radius+_t),-(outer_radius+_t),_w]) cube([(outer_radius+_t)*2,(outer_radius+_t)*2,(outer_radius+_t)*3]);
    translate([-(outer_radius+_t),-(outer_radius+_t),-(outer_radius+_t)*3-_w]) cube([(outer_radius+_t)*2,(outer_radius+_t)*2,(outer_radius+_t)*3]);

    rotate([90,0,0])
    hull() {
        rotate([0,10,0]) cylinder(r=4,h=(outer_radius+_t)*3);
        rotate([0,-10,0]) cylinder(r=4,h=(outer_radius+_t)*3);
    }
} */

```


[User]
I'm looking to create a customizable 2D origami light bulb design, similar to the one I saw on Thingiverse by mightynozzle. I want it to be parametric so I can easily adjust the size, thickness, and other aspects.

Specifically, I need a OpenSCAD file that will allow me to:

1.  Set the maximum size of the longest side of the design. The other dimension should be scaled proportionally to keep the aspect ratio correct.
2.  Control the overall height (thickness) of the model when extruded, for 3D printing or other purposes.
3.  Adjust the thickness of both the outer outline and the inner outline separately.
4.  Change the roundness of the edges on the inner outlines, allowing them to be sharper or more rounded.
5.  Have an option to flip (mirror) the model horizontally, as if viewing the bulb from the other side.

The base shape will come from a series of 2D coordinates and polygon definitions in the file; you'll need to translate these coordinates and polygon groupings into a usable OpenSCAD design.

I'd also like the output to be based on an extrusion of a 2D shape, so I can print it on a 3D printer. I don't think I need any special libraries beyond what comes with OpenSCAD by default, but if there's a clever way to accomplish this using a specific library, I'm open to suggestions.

[Assistant]
customizable_origami_light_bulb.scad:
```
/*
 * Customizable Origami - Light Bulb - https://www.thingiverse.com/thing:2738377
 * by Dennis Hofmann - https://www.thingiverse.com/mightynozzle/about
 * created 2017-12-30
 * version v1.0
 *
 * Changelog
 * --------------
 * v1.0:
 *      - final design
 * --------------
 *
 * This work is licensed under the Creative Commons - Attribution - NonCommercial - ShareAlike license.
 * https://creativecommons.org/licenses/by-nc-sa/3.0/
 */

 // Parameter Section //
//-------------------//

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

// The maximum size of the longest side. The shorter side will be automatically resized in same ratio.
max_size_in_millimeter = 120; //[20:300]

// The height of the model.
model_height_in_millimeter = 5; //[0.2:0.2:100]

// Thickness of the outer outline.
outline_size_in_millimeter = 1.4; //[0.5:0.1:20]

// Thickness of the inner outline.
inline_size_in_millimeter = 0.7; //[0.5:0.1:20]

// Roundiness of the ends of the inner outlines.
inline_edge_radius_in_millimeter = 0.3; //[0.0:0.1:5]

// Flip model
flip_model = "no"; //[yes,no]

/*[hidden]*/
max_size = max_size_in_millimeter;
model_height = model_height_in_millimeter;
$fn=32;

// Outer Points
A1 = [483, 386];
A2 = [581, 220];
A3 = [734, 171];
A4 = [887, 223];
A5 = [988, 389];
A6 = [859, 650];
A7 = [849, 737];
A8 = [849, 785];
A9 = [849, 834];
A10 = [849, 879];
A11 = [791, 940];
A12 = [677, 940];
A13 = [619, 879];
A14 = [619, 834];
A15 = [619, 785];
A16 = [619, 737];
A17 = [607, 647];

outline = [A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17];

// Inner Points
B1 = [590, 344];
B2 = [879, 340];
B3 = [811, 450];
B4 = [657, 450];
B5 = [690, 580];
B6 = [774, 580];
B7 = [774, 737];
B8 = [690, 737];
B9 = [740, 282];

// Polygons
C1 = [A2, A3, A4];
C2 = [A2, B9, A4];
C3 = [B9, B1, A2];
C4 = [B9, B2, A4];
C5 = [A2, B1, A1];
C6 = [A1, A17, B1];
C7 = [A4, A5, B2];
C8 = [A5, A6, B2];
C9 = [B1, B9, B2, A6, A7, B7, B6, B3, B4, B5, B8, A16, A17];
C10 = [B5, B6, B7, B8];
C11 = [B4, B3, B6, B5];
C12 = [A16, B8, B7, A7, A8, A15];
C13 = [A15, A8, A9, A14];
C14 = [A14, A9, A10, A13];
C15 = [A13, A10, A11, A12];

cut_polygons = [C1, C2, C3, C4, C5, C6, C7, C8, C9, C10, /*C11,*/ C12, C13, C14, C15];

min_x = A1[0];
min_y = A3[1];
max_x = A5[0];
max_y = A11[1];

x_size = max_x - min_x;
y_size = max_y - min_y;

x_factor = max_size / x_size;
y_factor = max_size / y_size;

inline_size = x_size > y_size ? inline_size_in_millimeter / x_factor / 2: inline_size_in_millimeter / y_factor / 2;
inline_edge_radius = x_size > y_size ? inline_edge_radius_in_millimeter / x_factor: inline_edge_radius_in_millimeter / y_factor;
outline_size = x_size > y_size ? outline_size_in_millimeter / x_factor - inline_size: outline_size_in_millimeter / y_factor - inline_size;

 // Program Section //
//-----------------//

if(x_size > y_size) {
    resize(newsize=[max_size, x_factor * y_size, model_height]){
        if(flip_model == "yes") {
            mirror([0,1,0]) {
                rotate([180,180,0]) {
                    create(outline, cut_polygons);
                }
            }
        } else {
            create(outline, cut_polygons);
        }
    }
} else {
    resize(newsize=[y_factor * x_size, max_size, model_height]){
        if(flip_model == "yes") {
            mirror([0,1,0]) {
                rotate([180,180,0]) {
                    create(outline, cut_polygons);
                }
            }
        } else {
            create(outline, cut_polygons);
        }
    }
}

 // Module Section //
//----------------//

module create() {
    linear_extrude(height=1) {
        difference() {
            offset(r = -0) {
                offset(r = +outline_size) {
                    polygon(points = outline, convexity = 10);
                }
            }

            for(cut_polygon = [0:len(cut_polygons)]) {
                offset(r = +inline_edge_radius) {
                    offset(r = -inline_size - inline_edge_radius) {
                        polygon(points = cut_polygons[cut_polygon], convexity = 10);
                    }
                }
            }
        }
    }
}

```


[User]
I'd like to design a cup holder that fits into a hole in my desk. I have a basic idea of what I need, and I even have a simple OpenSCAD file that shows my concept, but I want something more robust and parametric. It should be able to be easily customized for different hole sizes and cup sizes.

Here's a breakdown of what I'm looking for, building off my existing code:

**General Shape:** The cup holder will have a cylindrical shape with a lip at the top to prevent it from falling through the hole. The interior will be a hole that slopes inwards slightly towards the bottom to accommodate different sized cups.

**Key Parameters:**

*   **`top_id`**: Internal diameter at the top of the holder (where the cup enters).
*   **`top_od`**: Outer diameter at the top of the main body, designed to fit into the desk hole.
*   **`bottom_id`**: Internal diameter at the bottom of the holder.
*   **`il`**: Inner length (depth of the cup holding part).
*   **`lip_overhang`**: The amount the lip extends beyond the main body's outer diameter.
*   **`lip_height`**: The height of the lip.
*   **`$fa`**: A variable to control the fineness of the curved edges (smaller values mean more facets). I generally use 2, but it should still be able to be user controlled

**Structure:**

1.  **Main Body (Cup Holder):** This is the cylindrical portion with a sloped inner wall.
    *   The outer cylinder should be just slightly smaller than the `top_od` at its narrowest point so it slips into the hole. It should continue at a constant size to the end of the `il` depth.
    *   The inner wall should go from `top_id` at the top, to `bottom_id` at the bottom, over the `il` length.
2.  **Lip:** The lip sits on top of the main body and prevents the holder from falling through the desk hole.
    *   It has a cylinder with outer diameter of `top_od` + 2 * `lip_overhang`, and an inner diameter that goes from `top_id` to a bit narrower than `top_id` at the top of the inner edge of the lip to assist with inserting a glass.
3.  **Assembly:**  The lip should sit directly on top of the main body.

**Additional Requests:**

*   I'd really appreciate it if the code could be well-commented so it's easy for me to understand how it works and change the parameters if needed.
*   Please use the default `$fa` when constructing cylinders and other curved shapes, unless I have specified otherwise, so it doesn't take too long to render.

I would prefer if this could be in a single OpenSCAD file, if possible. I'm open to suggestions, but I think this should cover what I'm looking for. Thank you!

[Assistant]
drink_holder.scad:
```
// rounding variable. smaller numbers increase rounding of cylinders and spheres
$fa=2;

// top internal diameter. how wide the hole is at the top of the holder. This determines the widest glass you can fit
top_id = 73;

// top external diameter. how wide the holder will be at the top, just before the lip. this should be set to however wide the hole is you have in the table / desk / what have you
top_od = 80;

// bottom internal diameter. how wide the hole is at the bottom. this determines the largest glass that will fit all the way to the bottom. bottom outer diameter is determined by
bottom_id= 69;

// inner length. how deep the hole will be in the holder
il = 85;

// how many millimeters the lip extends past the top of the holder
lip_overhang = 4;
// how tall the lip is
lip_height = 5;

// calculated variables
wall_thickness = top_od - top_id;
ol = il + wall_thickness;
lip_od = top_od + lip_overhang * 2;
slant_amount = top_id - bottom_id;
slant_rate = (top_id - bottom_id) / il;

// the lip of the holder
module lip() {
    difference() {
        cylinder(d1=lip_od, d2=top_od, h=lip_height);
        // .001 is slop
        cylinder(d1=top_id, d2=top_id + slant_rate * lip_height, h=lip_height);
    }
}

// the part that actually holds the glass
module cup() {
    difference() {
      // no bottom od so the cup holds to the sides
      cylinder(d1=top_od - 2, d2=top_od, h=ol);
      translate([0,0,wall_thickness]) cylinder(d1=bottom_id, d2=top_id, h=il);
    }
}

// the whole shebang
module drink_holder() {
    cup();
    translate([0,0,ol]) lip();
}

drink_holder();

```


[User]
Hi, I'm looking to create a customizable project box lid using OpenSCAD. I need a design that allows me to specify the width and height of the lid, as well as the positions of screw holes. The lid should have a small lip that extends down into the box to add some support - like a small lip.

Here's what I'm thinking in terms of parameters:

*   `width`: The overall width of the lid.
*   `height`: The overall height of the lid.
*   `x_hole_distance`: The distance of the screw holes from the left and right edges.
*   `y_hole_distance`: The distance of the screw holes from the top and bottom edges.
*   `lip_depth`: The depth of the lip that extends down from the lid. This is something I'd like to control.

The lid itself should consist of a flat top surface with a lip that extends downward around the edges. The screw holes should be countersunk.

Could you generate the OpenSCAD code for this? I'd like to be able to easily customize these parameters. Thanks!

[Assistant]
customizable_project_box_lid.scad:
```
// All measurements in mm.

// The model is built with the top upwards so
// that you can more easily position holes and
// such. Make sure to flip it over for printing.

// The width of the lid.
width = 132;

// The height of the lid.
height = 81;

// The distance to place screw holes from the left/right edge.
x_hole_distance = 6;

// The distance to place screw holes from the top/bottom edge.
y_hole_distance = 6;

$fn = 50 * 1;

difference() {

    union() {
        cube([width, height, 1]);
        translate([1, 1, -4]) {
            cube([width - 2, height - 2, 4]);
        }
    }

    translate([x_hole_distance, y_hole_distance, 0]) {
        cylinder(100, 2, 2, true);
    }
    translate([x_hole_distance, y_hole_distance, -51]) {
        cylinder(100, 8, 8, true);
    }

    translate([x_hole_distance, height - y_hole_distance, 0]) {
        cylinder(100, 2, 2, true);
    }
    translate([x_hole_distance, height - y_hole_distance, -51]) {
        cylinder(100, 8, 8, true);
    }

    translate([width - x_hole_distance, y_hole_distance, 0]) {
        cylinder(100, 2, 2, true);
    }
    translate([width - x_hole_distance, y_hole_distance, -51]) {
        cylinder(100, 8, 8, true);
    }

    translate([width - x_hole_distance, height - y_hole_distance, 0]) {
        cylinder(100, 2, 2, true);
    }
    translate([width - x_hole_distance, height - y_hole_distance, -51]) {
        cylinder(100, 8, 8, true);
    }

 }

```


[User]
I'd like to create a customizable 2D origami crocodile head design using OpenSCAD. I want to be able to control the overall size, height, and the thickness of both the outer and inner outlines. The design is based on a set of predefined points and polygons, which I have listed below. The final model should be created using linear extrusion.

Here are the specific details:

**Parameters:**

*   `max_size_in_millimeter`: The maximum size of the longest side of the model, with the shorter side scaling proportionally. Allow values between 20 and 300.
*   `model_height_in_millimeter`: The height of the extruded model, ranging from 0.2 to 100 in increments of 0.2.
*   `outline_size_in_millimeter`: The thickness of the outer outline, with a range of 0.5 to 20 in 0.1 increments.
*   `inline_size_in_millimeter`: The thickness of the inner outlines, also with a range of 0.5 to 20 in 0.1 increments.
*   `inline_edge_radius_in_millimeter`: The radius for rounding the ends of inner outlines, between 0.0 and 5 in 0.1 increments.
*   `flip_model`: A boolean option, "yes" or "no", for mirroring the model across the y-axis.

**Points:**

```
// Outer Points
A1 = [119, 595];
A2 = [189, 512];
A3 = [240, 489];
A4 = [512, 458];
A5 = [808, 391];
A6 = [1086, 179];
A7 = [1322, 271];
A8 = [1559, 276];
A12 = [1746, 392];
A13 = [1810, 663];
A15 = [1346, 1087];
A16 = [1085, 1066];
A18 = [990, 1068];
A19 = [417, 932];
A20 = [270, 812];
A21 = [289, 776];
A22 = [240, 696];
A23 = [241, 750];
A24 = [202, 699];
A25 = [205, 762];
A26 = [164, 691];

// Inner Points
B1 = [543, 557];
B2 = [796, 510];
B3 = [932, 330];
B4 = [1077, 318];
B5 = [1086, 242];
B6 = [1254, 324];
B7 = [1088, 386];
B8 = [1445, 506];
B9 = [952, 612];
B10 = [1046, 688];
B11 = [982, 823];
B12 = [860, 828];
B13 = [844, 766];
B14 = [788, 834];
B15 = [748, 833];
B16 = [726, 766];
B17 = [667, 835];
B18 = [611, 837];
B19 = [572, 752];
B20 = [521, 841];
B21 = [460, 845];
B22 = [420, 758];
B23 = [365, 851];
B24 = [310, 810];
B25 = [336, 679];
B26 = [407, 759];
B27 = [425, 650];
B28 = [449, 648];
B29 = [502, 706];
B30 = [517, 620];
B31 = [571, 614];
B32 = [609, 673];
B33 = [653, 612];
B34 = [702, 611];
B35 = [738, 711];
B36 = [794, 606];
```

**Polygons:**

```
// Polygons
C1 = [A1, A2, A22];
C2 = [A1, A22, A24, A26];
C5 = [A2, B1, A22];
C6 = [A22, B1, B36, B34, B33, B31, B30, B28, B27, B25];
C7 = [A2, A3, A4];
C8 = [A2, B1, A4];
C9 = [A4, A5, B1];
C10 = [B1, B2, A5];
C11 = [A5, A6, B5, B3, B2];
C12 = [B3, B7, B2];
C13 = [B3, B5, B4];
C14 = [B5, B6, B4];
C15 = [B3, B4, B7];
C16 = [B4, B6, B7];
C17 = [A6, B6, B5];
C18 = [A6, A7, B6];
C19 = [A7, A8, B6];
C20 = [B6, B8, A12];
C21 = [B6, A8, A12];
C22 = [B8, A12, A13];
C23 = [B8, A15, A13];
C24 = [B8, A15, A16];
C27 = [A19, A16, A18];
C28 = [A20, B23, A16, A18, A19];
C29 = [B2, B7, B6, B8];
C30 = [B2, B9, B8];
C31 = [B2, B9, B36, B1];
C32 = [B9, B8, B11, B10];
C33 = [B8, A16, B11];
C34 = [B23, B21, B20, B18, B17, B15, B14, B12, B11, A16];
C45 = [B24, B25, B26, B27, B28, B29, B30, B31, B32, B33, B34, B35, B36, B9, B10, B11, B12, B13, B14, B15, B16, B17, B18, B19, B20, B21, B22, B23];
```
The polygons above should be stored in a `cut_polygons` list:
```
cut_polygons = [C1, C2, C5, C6, C7, C8, C9, C10, C11, C12, C13, C14, C15, C16, C17, C18, C19, C20, C21, C22, C23, C24, C27, C28, C29, C30, C31, C32, C33, C34, C45];
```
The outer outline is formed by the points in the `outline` list:
```
outline = [A1, A2, A3, A4, A5, A6, A7, A8, A12, A13, A15, A16, A18, A19, A20, A21, A22, A23, A24, A25, A26];
```

**Implementation Details:**

1.  The model should first determine the bounding box of the outline to calculate scaling factors. The scaling should ensure that the maximum size is respected, with the smaller side being scaled proportionally, which will maintain the aspect ratio.
2.  The outer outline should be generated by offsetting the polygon defined by the `outline` points by `outline_size`.
3.  The inner cutouts should be generated by offsetting the polygon for each `cut_polygon` by `inline_edge_radius`, then again by `-inline_size - inline_edge_radius` to create the inner cutouts and rounded corners.
4.  All of this should then be extruded to the specified `model_height`.
5.  I need to mirror the object across the y-axis if `flip_model` is set to "yes" and rotate 180 degrees on x and y axis.

I'd like the final output to be a single .scad file that I can open in OpenSCAD and render. It doesn't seem like I'll need any libraries for this.

[Assistant]
customizable_origami_crocodile_head.scad:
```
/*
 * Customizable Origami - Crocodile Head - https://www.thingiverse.com/thing:2739696
 * by Dennis Hofmann - https://www.thingiverse.com/mightynozzle/about
 * created 2017-12-31
 * version v1.0
 *
 * Changelog
 * --------------
 * v1.0:
 *      - final design
 * --------------
 *
 * This work is licensed under the Creative Commons - Attribution - NonCommercial - ShareAlike license.
 * https://creativecommons.org/licenses/by-nc-sa/3.0/
 */

 // Parameter Section //
//-------------------//

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

// The maximum size of the longest side. The shorter side will be automatically resized in same ratio.
max_size_in_millimeter = 120; //[20:300]

// The height of the model.
model_height_in_millimeter = 5; //[0.2:0.2:100]

// Thickness of the outer outline.
outline_size_in_millimeter = 1.6; //[0.5:0.1:20]

// Thickness of the inner outline.
inline_size_in_millimeter = 0.8; //[0.5:0.1:20]

// Roundiness of the ends of the inner outlines.
inline_edge_radius_in_millimeter = 0.3; //[0.0:0.1:5]

// Flip model
flip_model = "no"; //[yes,no]

/*[hidden]*/
max_size = max_size_in_millimeter;
model_height = model_height_in_millimeter;
$fn=32;

// Outer Points
A1 = [119, 595];
A2 = [189, 512];
A3 = [240, 489];
A4 = [512, 458];
A5 = [808, 391];
A6 = [1086, 179];
A7 = [1322, 271];
A8 = [1559, 276];
A12 = [1746, 392];
A13 = [1810, 663];
A15 = [1346, 1087];
A16 = [1085, 1066];
A18 = [990, 1068];
A19 = [417, 932];
A20 = [270, 812];
A21 = [289, 776];
A22 = [240, 696];
A23 = [241, 750];
A24 = [202, 699];
A25 = [205, 762];
A26 = [164, 691];

outline = [A1, A2, A3, A4, A5, A6, A7, A8, A12, A13, A15, A16, A18, A19, A20, A21, A22, A23, A24, A25, A26];

// Inner Points
B1 = [543, 557];
B2 = [796, 510];
B3 = [932, 330];
B4 = [1077, 318];
B5 = [1086, 242];
B6 = [1254, 324];
B7 = [1088, 386];
B8 = [1445, 506];
B9 = [952, 612];
B10 = [1046, 688];
B11 = [982, 823];
B12 = [860, 828];
B13 = [844, 766];
B14 = [788, 834];
B15 = [748, 833];
B16 = [726, 766];
B17 = [667, 835];
B18 = [611, 837];
B19 = [572, 752];
B20 = [521, 841];
B21 = [460, 845];
B22 = [420, 758];
B23 = [365, 851];
B24 = [310, 810];
B25 = [336, 679];
B26 = [407, 759];
B27 = [425, 650];
B28 = [449, 648];
B29 = [502, 706];
B30 = [517, 620];
B31 = [571, 614];
B32 = [609, 673];
B33 = [653, 612];
B34 = [702, 611];
B35 = [738, 711];
B36 = [794, 606];

// Polygons
C1 = [A1, A2, A22];
C2 = [A1, A22, A24, A26];
C5 = [A2, B1, A22];
C6 = [A22, B1, B36, B34, B33, B31, B30, B28, B27, B25];
C7 = [A2, A3, A4];
C8 = [A2, B1, A4];
C9 = [A4, A5, B1];
C10 = [B1, B2, A5];
C11 = [A5, A6, B5, B3, B2];
C12 = [B3, B7, B2];
C13 = [B3, B5, B4];
C14 = [B5, B6, B4];
C15 = [B3, B4, B7];
C16 = [B4, B6, B7];
C17 = [A6, B6, B5];
C18 = [A6, A7, B6];
C19 = [A7, A8, B6];
C20 = [B6, B8, A12];
C21 = [B6, A8, A12];
C22 = [B8, A12, A13];
C23 = [B8, A15, A13];
C24 = [B8, A15, A16];
C27 = [A19, A16, A18];
C28 = [A20, B23, A16, A18, A19];
C29 = [B2, B7, B6, B8];
C30 = [B2, B9, B8];
C31 = [B2, B9, B36, B1];
C32 = [B9, B8, B11, B10];
C33 = [B8, A16, B11];
C34 = [B23, B21, B20, B18, B17, B15, B14, B12, B11, A16];
C45 = [B24, B25, B26, B27, B28, B29, B30, B31, B32, B33, B34, B35, B36, B9, B10, B11, B12, B13, B14, B15, B16, B17, B18, B19, B20, B21, B22, B23];

cut_polygons = [C1, C2, C5, C6, C7, C8, C9, C10, C11, C12, C13, C14, C15, C16, C17, C18, C19, C20, C21, C22, C23, C24, C27, C28, C29, C30, C31, C32, C33, C34, C45];

min_x = A1[0];
min_y = A6[1];
max_x = A13[0];
max_y = A15[1];

x_size = max_x - min_x;
y_size = max_y - min_y;

x_factor = max_size / x_size;
y_factor = max_size / y_size;

inline_size = x_size > y_size ? inline_size_in_millimeter / x_factor / 2: inline_size_in_millimeter / y_factor / 2;
inline_edge_radius = x_size > y_size ? inline_edge_radius_in_millimeter / x_factor: inline_edge_radius_in_millimeter / y_factor;
outline_size = x_size > y_size ? outline_size_in_millimeter / x_factor - inline_size: outline_size_in_millimeter / y_factor - inline_size;

 // Program Section //
//-----------------//

if(x_size > y_size) {
    resize(newsize=[max_size, x_factor * y_size, model_height]){
        if(flip_model == "yes") {
            mirror([0,1,0]) {
                rotate([180,180,0]) {
                    create(outline, cut_polygons);
                }
            }
        } else {
            create(outline, cut_polygons);
        }
    }
} else {
    resize(newsize=[y_factor * x_size, max_size, model_height]){
        if(flip_model == "yes") {
            mirror([0,1,0]) {
                rotate([180,180,0]) {
                    create(outline, cut_polygons);
                }
            }
        } else {
            create(outline, cut_polygons);
        }
    }
}

 // Module Section //
//----------------//

module create() {
    linear_extrude(height=1) {
        difference() {
            offset(r = -0) {
                offset(r = +outline_size) {
                    polygon(points = outline, convexity = 10);
                }
            }

            for(cut_polygon = [0:len(cut_polygons)]) {
                offset(r = +inline_edge_radius) {
                    offset(r = -inline_size - inline_edge_radius) {
                        polygon(points = cut_polygons[cut_polygon], convexity = 10);
                    }
                }
            }
        }
    }
}

```


[User]
Hi, I'd like an OpenSCAD design for a shaver holder that mounts to the IKEA GRUNDTAL bathroom corner shelf. It should be customizable in terms of length and also allow for some text to be either embossed or stenciled onto the surface. It also needs to account for the fact that it has a rounded hook for the shaver handle to sit in. I don't really have any particular preferences in terms of libraries - just want to make sure the code is clean and efficient. Here are the key specs and customization I have in mind:

**Core Design:**

*   The holder should have two "hooks": a larger one at the bottom for the shaver handle, and a smaller one at the top to attach to the GRUNDTAL shelf.
*   There should be a backplate to connect these two hooks and mount against the shelf.
*   There needs to be a cutout on the lower hook to accommodate the shaver handle, it should be a circular cutout mostly removed on one side.

**Customization Parameters (via Customizer):**

*   `h2`:  Length/height of the backplate
*   `mytext`: Text to print on the holder.
*   `embossed`:  A boolean (1 for true, 0 for false) flag to control whether the text should be embossed or stenciled.
*   `mytextsize`: Size of the text.
*   `fontName`: A dropdown selection list with the following predefined fonts: "Helvetica", "Helvetica Light", "Roboto", "Roboto Condensed", "Oswald", "Playfair Display", "Indie Flower", "Audiowide", "Coustard", "Manual"
*   `manualFont`: A text input that will only be used if `fontName` is set to "Manual".

**Other Fixed Dimensions:**

*   `z1`: Overall width of the hooks.
*   `cut_w`: Width of the cutout on the lower shaver holder
*   `d1`: Diameter of the lower hook
*   `d2`: Diameter of the upper hook
*   `mat`: Material thickness
*   `$fn` :  $fn=100
*  `dt1` : `0.001`
*  `dt2` : `dt1 * 2`

I also want to specify that the model should be rotated 90 degrees before rendering. The overall design should be robust to printing with the overhang of the bottom hook and might require some support when printing, so keep that in mind if you have an opinion on how to model it. The original design included some fixes to avoid customizer bugs but I am sure the generated model will be fine in that regard. Let me know if you have any questions.

[Assistant]
GRUNDTAL_Shaver_Holder_v4_Customizer.scad:
```
/** *** ***** ******* ***********
//
// IKEA GRUNDTAL Shaver Holder
// Version 4 - 2017-12-30 : Customizer
// CC-BY-NC-SA December 2017 by ohuf@Thingiverse
//
// www.thingiverse.com/thing:2739758

(English text: scroll down...)

Ein einfacher Halter für einen Einweg-Nassrasierer.
Der Halter passt an das "GRUNDTAL" Eckregal von IKEA (s.Fotos).

Anpassbare Version: Benutze den Customizer um die Länge des Halters festzulegen.
Außerdem lässt sich auf dem Halter ein kurzer, einzeiliger Text aufdrucken - oder eingravieren.

Wenn du einen hergestellt hast, lass es mich über "I Made One" wissen!

Konstruiert in OpenSCAD: viel Spaß beim Remixen!

-- --- ----- ------- -----------

This is a simple shaver holder for an IKEA "GRUNDTAL" bathroom corner shelf. I made this one in OpenSCAD.

See the photos for reference:
This is a customizable version. you can define the length of the holder as well as a short one-liner text. The text can be embossed on the holder or it can be stenciled out. Several different fonts and styles have been pre-defined in the customizer.

Enjoy, have fun remixing and let me know when you've made one, and what for!

//
// License: CC-BY-NC-SA by oli@huf.org
// read all about it here: http://creativecommons.org/licenses/by-nc-sa/4.0/
//
** *** ***** ******* ***********/

/* [Text on Holder] */
// - Text to print or stencil out on the hanger. Leave empty for no text.
mytext="Hers";

// - Embossed Text or Stenciled Text
embossed=1; //[1:Embossed, 0:Stenciled]

// - Size of the text; Default is 12
mytextsize=12;

// - Thingiverse suppports the Google Fonts (https://fonts.google.com/). This is a subset.
fontName="Helvetica Light"; // [Helvetica, Helvetica Light, Roboto, Roboto Condensed, Oswald, 	Playfair Display, Indie Flower, Audiowide, Coustard, Manual]

// - If the font name selection is "Manual", this font will be used. Default is "Roboto Condensed". You could add Style modifiers like this: "Roboto Condensed:style=Bold". See https://fonts.google.com/ for more fonts.
manualFont="Roboto Condensed";

/* [Size of the holder] */
// Length of the holder || Länge (Höhe) des Halters
h2 = 75;

/* [Hidden] */
z1=44;		// object's width
cut_w=25;	// width of cut-out for the shaver's handle
d1=14;	// Radius of the lower "hook" for the shaver
d2=11; 	// Radius of the upper hook where it hangs in the "GRUNDTAL" rack
mat=1;	// material thickness

$fn=100;
dt1=0.001;
dt2=dt1*2;

//fontName="Helvetica Thin"; // [Helvetica, Helvetica Light, Palatino, Portago, Papyrus, Helvetica Thin, Arial, Arial Narrow, American Typewriter, American Typewriter Semibold]font1="Helvetica Neue";
// Local font list on my Mac ;-)
font2="Helvetica:style=Light";
font3="Palatino Linotype:style=standard";
font4="PortagoITC TT";
font5="Papyrus";
font6="Helvetica Neue:style=Thin"; 	// :-)
font7="Arial";
font8="Arial Narrow";
font9="American Typewriter";
font10="American Typewriter:style=Semibold";

//myfont=font6;		// see font list
myfont=isManualFont() ? manualFont : getFont();

rotate([-90,0,0])
difference(){
	union(){
		difference(){
			union(){
				cylinder(d=d1, h=z1);
			}
			union(){
				// Rasierer-Halte-Haken unten:
				translate([0, 0, -dt1])	// fix for customizer bug
				cylinder(d=d1-2*mat, h=z1+dt2);
				translate([-d1/2-2,-d1/2, -dt1])	// vorne leicht umzogen, um Rasierer zu halten (support!)
				cube([d1/2+dt2, d1/2+dt2, z1+dt2]);	// Abschnitt vorne (Kreisviertel und mehr)
				translate([-d1/2, 0, -dt1])
				cube([d1/2+dt2, d1/2+dt2, z1+dt2]);		// Abschnitt hinten (Kreisviertel)
				translate([-d1/2,-d1/2, z1/2-cut_w/2])
				cube([d1, d1/2, cut_w]);
			}
		}
		// Hintere Platte nach oben:
		translate([-h2,d1/2-mat, 0])
		cube([h2, mat, z1+dt1]);

		// Halte-Haken Oben:
		translate([-h2, (d1-d2)/2, 0])
		difference(){
			cylinder(d=d2, h=z1);
			union(){
				translate([0, 0, -dt1])	// fix for customizer bug
				cylinder(d=d2-2*mat, h=z1+dt2);
				translate([0,-d2/2, -dt1])
				cube([d2/2, d2, z1+dt2]);
			}
		}

		//// Text embossed:
		if(embossed==1)
			initial( mytext );

	}

	// Text cut out:
	if(embossed==0){
		translate([0, 1, -dt1])
		initial( mytext );
	}
//initial( "His" );
//	color("red")
//	translate([-12, 10, z1/2])
//	rotate([90, -90, 0])
//	linear_extrude(height = 10) {
//		text("His", font = font1, size = 17, direction = "ltr", halign="center", valign="bottom", spacing = 1 );
//	}

}

module initial ( txt ) {
		color("red")
	translate([-12, d1/2, z1/2])
	rotate([90, -90, 0])
	linear_extrude(height = mat+1+dt2) {
		text(txt, font = myfont, size = mytextsize, direction = "ltr", halign="center", valign="baseline", spacing = 1 );
	}
}

function isManualFont() = fontName == "Manual" ? true : false;

function getFont() = fontName == "Helvetica" ? "Helvetica Neue"
	: fontName == "Helvetica Light" ? "Helvetica:style=Light"
	: fontName == "Palatino" ? "Palatino Linotype:style=standard"
	: fontName == "Portago" ? "PortagoITC TT"
	: fontName == "Papyrus" ? "Papyrus"
	: fontName == "Arial" ? "Arial"
	: fontName == "Arial Narrow" ? "Arial Narrow"
	: fontName == "American Typewriter" ? "American Typewriter"
	: fontName == "American Typewriter Semibold" ? "American Typewriter:style=Semibold"
	: fontName == "Roboto" ? "Roboto:style=Medium"
	: fontName == "Roboto Condensed" ? "Roboto Condensed"
	: fontName == "Oswald" ? "Oswald"
	: fontName == "Playfair Display" ? "Playfair Display"
	: fontName == "Indie Flower" ? "Indie Flower"
	: fontName == "Audiowide" ? "Audiowide"
	: fontName == "Coustard" ? "Coustard"
	: fontName == "Manual" ? "Manual"
	: fontName;

```


[User]
I'm looking to create a customizable nut driver that I can 3D print. I want it to have a nut socket on one side and a hex drive hole on the other, so I can insert a hex key and use it like a socket driver. The basic idea is similar to the example code I've included below, but I need it to be more flexible and well-parameterized.

Here are the details:

*   **Overall Shape:** The driver should be cylindrical overall, with the nut socket and hex drive hole aligned on the central axis, on opposite sides of the cylinder.
*   **Nut Socket:**
    *   I need to be able to specify the nut size (diameter across flats).
    *   I need to specify the socket's depth (how far the nut will sit inside).
    *   I want a wall thickness surrounding the nut socket to keep it strong.
*   **Hex Drive Hole:**
    *   I need to be able to specify the hex size (diameter across flats).
    *   I need to specify the hex hole's depth.
*  **Gap:** I need to specify a gap between the base of the nut socket and the base of the hex drive hole.
*   **Hole Scaling & Offset:** My 3D printer sometimes makes holes come out too small, so I need parameters to scale and/or add an offset to the sizes of the nut socket and hex driver hole.
*   **Round or Hex Shaft:** I want to specify if the shaft (cylinder that surrounds the nut socket, hex hole, and gap) is round or hex.
*   **Parameters:** All of the key dimensions (nut size, hex size, depths, wall thickness, gap, scaling, offset, and round/hex) should be defined using parameters that I can easily change.
*   **Libraries:** I'd like to use the `BOSL2` library if possible for any utility functions.

Here's the basic OpenSCAD code example I mentioned:

```openscad
// Simple nutdriver example -- Al Williams

// Type of shaft
$fn=128;  // [6:hex, 128:round]
// Size of nut (a little larger than the nut is good)
nutsize=6.2;
// Size of hex driver side -- should be tight
hexsize=2;
// Size of wall around nut
wall=1;
// Socket height
sock_height=4;
// Drive height
drive_height=4;
// Gap between drive and socket
gap=3;

// Scale up holes by factor if your printer/slicer makes holes small
holescale=1;
// Add a bit to holes if your printer/slicer makes holes small (make negative if they come out big)
holeoffset=0.5;

nut_size=nutsize*holescale+holeoffset;
hex_size=hexsize*holescale+holeoffset;

difference()
{
   translate([0,0,-(drive_height+gap/2)]) cylinder(d=nut_size+2*wall,h=sock_height+drive_height+gap,center=false);
   translate([0,0,gap/2]) cylinder(d=nut_size,$fn=6,h=sock_height+2,center=false);
   translate([0,0,-(drive_height+gap/2+2)])
      cylinder(d=hex_size,$fn=6,h=drive_height+2,center=false);
}
```

Can you generate the required OpenSCAD file or files to achieve this?

[Assistant]
nutdriver.scad:
```
// Simple nutdriver example -- Al Williams

// Type of shaft
$fn=128;  // [6:hex, 128:round]
// Size of nut (a little larger than the nut is good)
nutsize=6.2;
// Size of hex driver side -- should be tight
hexsize=2;
// Size of wall around nut
wall=1;
// Socket height
sock_height=4;
// Drive height
drive_height=4;
// Gap between drive and socket
gap=3;

// Scale up holes by factor if your printer/slicer makes holes small
holescale=1;
// Add a bit to holes if your printer/slicer makes holes small (make negative if they come out big)
holeoffset=0.5;

nut_size=nutsize*holescale+holeoffset;
hex_size=hexsize*holescale+holeoffset;

difference()
{
   translate([0,0,-(drive_height+gap/2)]) cylinder(d=nut_size+2*wall,h=sock_height+drive_height+gap,center=false);
   translate([0,0,gap/2]) cylinder(d=nut_size,$fn=6,h=sock_height+2,center=false);
   translate([0,0,-(drive_height+gap/2+2)])
      cylinder(d=hex_size,$fn=6,h=drive_height+2,center=false);
}
```