[User]
I'd like to create a customizable 2D origami model of a llama using OpenSCAD. I'm looking for a design that allows me to adjust the overall size, height, and thickness of both the outer and inner outlines.

The design should start with a set of predefined points that form the llama's outer shape, which I've labeled A1 through A25. There should also be points B1-B3 defining the locations of some interior elements, with polygons C1-C12 defining inner cutout sections of the design. Here are the coordinates for the A, B and C lists as used in the original SCAD file:

```
// Outer Points
A1 = [30, 1074];
A2 = [56, 805];
A3 = [231, 683];
A4 = [1203, 738];
A5 = [1283, 109];
A6 = [1286, 9];
A7 = [1373, 68];
A8 = [1388, 55];
A9 = [1471, 55];
A10 = [1675, 228];
A11 = [1684, 289];
A12 = [1451, 296];
A13 = [1453, 1063];
A14 = [1029, 1420];
A15 = [1020, 1481];
A16 = [1096, 1539];
A17 = [963, 1539];
A18 = [959, 1388];
A19 = [538, 1151];
A20 = [188, 1349];
A21 = [193, 1481];
A22 = [261, 1539];
A23 = [140, 1539];
A24 = [134, 1216];
A25 = [69, 999];

// Inner Points
B1 = [166, 1359];
B2 = [1403, 165];
B3 = [69, 974];

// Polygons
C1 = [A5, A6, A7];
C2 = [A8, A9, B2, A12, A4, A5, A7];
C3 = [A9, A10, A11, A12, B2];
C4 = [A12, A13, A4];
C5 = [A13, A14, A4];
C6 = [A14, A15, A16, A17, A18];
C7 = [A14, A4, A19];
C8 = [A19, A4, A3];
C9 = [A3, A19, B3];
C10 = [A3, A2, A1, A25, B3];
C11 = [A25, B3, A19, A20, B1, A24];
C12 = [A24, B1, A20, A21, A22, A23];
```

The outer outline should be generated by connecting the A points. The inner details should be generated using the C polygon lists, which will be cut out of the overall outline.

I'd like to be able to specify:
*   `max_size_in_millimeter`: The maximum dimension of the model. The other dimension should scale proportionally.
*   `model_height_in_millimeter`: The height of the extruded 2D model.
*   `outline_size_in_millimeter`: The thickness of the outer outline.
*   `inline_size_in_millimeter`: The thickness of the inner outlines (cutouts).
*  `inline_edge_radius_in_millimeter`: The rounding radius for the inner outline corners.
* `flip_model`: A boolean option to mirror the model along the y-axis.

The design should automatically calculate scaling factors to fit the model within the `max_size_in_millimeter` and handle cases where the x or y dimension is greater. I also need the inner and outer outline sizes to be adjusted for scaling so that they remain the specified thickness.

The core logic should generate the base shape with the outer outline, cut out the inner polygons using offsets, and apply the user-defined extrusion height. Please keep the code reasonably organized and readable. I don't need any external libraries for this.

[Assistant]
customizable_origami_lama.scad:
```
/*
 * Customizable Origami - Lama - https://www.thingiverse.com/thing:2621180
 * by Dennis Hofmann - https://www.thingiverse.com/mightynozzle/about
 * created 2017-11-02
 * 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.7; //[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 = [30, 1074];
A2 = [56, 805];
A3 = [231, 683];
A4 = [1203, 738];
A5 = [1283, 109];
A6 = [1286, 9];
A7 = [1373, 68];
A8 = [1388, 55];
A9 = [1471, 55];
A10 = [1675, 228];
A11 = [1684, 289];
A12 = [1451, 296];
A13 = [1453, 1063];
A14 = [1029, 1420];
A15 = [1020, 1481];
A16 = [1096, 1539];
A17 = [963, 1539];
A18 = [959, 1388];
A19 = [538, 1151];
A20 = [188, 1349];
A21 = [193, 1481];
A22 = [261, 1539];
A23 = [140, 1539];
A24 = [134, 1216];
A25 = [69, 999];

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];

// Inner Points
B1 = [166, 1359];
B2 = [1403, 165];
B3 = [69, 974];

// Polygons
C1 = [A5, A6, A7];
C2 = [A8, A9, B2, A12, A4, A5, A7];
C3 = [A9, A10, A11, A12, B2];
C4 = [A12, A13, A4];
C5 = [A13, A14, A4];
C6 = [A14, A15, A16, A17, A18];
C7 = [A14, A4, A19];
C8 = [A19, A4, A3];
C9 = [A3, A19, B3];
C10 = [A3, A2, A1, A25, B3];
C11 = [A25, B3, A19, A20, B1, A24];
C12 = [A24, B1, A20, A21, A22, A23];

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

min_x = A1[0];
min_y = A6[1];
max_x = A11[0];
max_y = A16[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]
Okay, I need a parametric tap holder designed in OpenSCAD. I've got a bunch of taps of varying sizes and I want to store them upright in a cylindrical case with a screw-on lid. I'm envisioning a circular arrangement of tap-sized holes, plus a larger center hole for my smallest taps.

The tap holder should have the following features:

*   **Cylindrical Body:** The main body of the holder should be a cylinder with a height parameter.
*   **Screw-on Lid:** The lid should screw onto the body using a threaded connection, and it should have a slightly larger diameter on top than the threaded section, with a smooth transition, and also some little notches around the edge to make it easier to grip. The lid should have a hollowed-out section in the top, and the screw threads should be on the bottom edge.
*   **Tap Holes:** There should be a configurable number of holes around a circle within the main body. Each hole should have its own diameter and height parameter.
*   **Center Hole:** There should also be a larger, fixed-size hole in the center of the body for my smallest taps.
*   **Wall Thickness:** There should be a parameter to define the thickness of the wall of the main cylinder.
*   **Path Radius:** The circular path of the tap holes should have a radius that is also a parameter.
*   **Thread:** The lid and body should use standard English threads. I am open to using other thread options if needed.

I need the following parameters to be configurable in the OpenSCAD file(s):

*   `caseHeight`: The overall height of the main body, not including the threaded part.
*   `caseRadius`: The radius of the cylinder that makes up the main body and lid.
*   `wall`: The thickness of the cylinder wall.
*   `pathRadius`: The radius of the circle on which tap holes are placed.
*   `numHoles`: The number of tap holes around the circle.
*   `tapArray`: A 2D array/list containing the diameter and height of each tap hole like `[[diameter1, height1], [diameter2, height2], ...]`.
*   A parameter for the larger fixed-size hole.
*   The specific thread parameters, including size, tpi, and the tolerance.

I'm using the `threads.scad` library for the threads. I'd also like to avoid using any hardcoded values where possible, instead using parameters throughout. The notches around the lid edge should be evenly distributed, and also parameterized (i.e. the number of notches should be a parameter).

[Assistant]
tap_holder.scad:
```
use <threads.scad>

$fn = 200;

// diameter,height
tapArray = [
[12,75],
[10,65],
[8,63],
[6,60],
[5,55],
[4,50],
[3.5,44],
[3,41]
];

numHoles = len(tapArray);
caseHeight = 68; // has to be more than tallest tap minus wall
pathRadius = 18;
wall = 10;
caseRadius = 33;

// lid
translate([0,0,caseHeight+20])
{
    difference()
    {
        union()
        {
            // unthreaded top
            translate([0,0,wall])
            {
                difference()
                {
                    cylinder(r=caseRadius, h=23);
                    cylinder(r=caseRadius-2, h=20);
                }
            }

            // threaded bottom
            difference()
            {
                cylinder(r=caseRadius, h=wall);
                scale([1.05,1.05,1]) english_thread(2.3, 4, 0.5, internal=true);
            }
        }

        // notches around edge
        for (i=[0:10])
        {
            translate([(caseRadius+1)*cos(i*(360/10)),(caseRadius+1)*sin(i*(360/10)),-5]) cylinder(d=4,h=40);
        }
    }
}

// main body
difference()
{
    union()
    {
        cylinder(r=caseRadius, h=caseHeight-wall);
        translate([0,0,caseHeight-wall]) english_thread(2.3, 4, 0.5);
    }

    union()
    {
        // big hole for all tiny taps
        translate([0,0,caseHeight-20]) cylinder(r=6, h=30);

        // individual holes for larger taps
        for (i=[0:numHoles-1])
        {
            translate([pathRadius*cos(i*(360/numHoles)),pathRadius*sin(i*(360/numHoles)),caseHeight-tapArray[i][1]+wall])
                cylinder(d=tapArray[i][0]+1,h=tapArray[i][1]);
        }
    }
}

```


[User]
Hi, I'm looking for a parametric OpenSCAD design for a bit holder, kind of like the one I have now but I need to be able to customize it more easily. I'm hoping you can generate the SCAD files for me.

The basic idea is a holder for hex-shaped screwdriver bits. I need to be able to specify how many slots there are in a single row, the diameter of each slot (measured flat-to-flat), the spacing between each slot, and how far the first and last slots are from the edges of the holder.

I also want to control the height of the base underneath the slots, and the height of the slots themselves. It needs to be possible to make it a single-sided or double-sided holder. If it's double-sided, the two sets of slots should be back-to-back.

Finally, I need the option to add walls on the front and back of the holder for extra stiffness. I'd like to be able to set the thickness of these walls.

So, to recap, I need parameters for:

*   Number of slots in a row
*   Slot diameter (flat-to-flat)
*   Double-sided option (yes/no)
*   Distance between first/last slot and the edges
*   Distance between slots
*   Height of the floor below the slots
*   Height of the slots
*   Thickness of the back wall (0 for none)
*   Thickness of the front wall (0 for none)

I don't need any extra bells or whistles, just a clean, functional design. I am not using any specific libraries (like MCAD) and would prefer that the design not rely on external libraries.

[Assistant]
Bitholder_V01a.scad:
```
// Minimalist bit holder V01a
// 2017/11/04
// Licensed under the Creative Commons - Attribution - Non-Commercial -
// Share Alike license.
//
// Minimalist bit holder to organize bits in a small space, e.g. for an
// EDC tool pouch.
// Number of bits, spacing, double/single sided, etc. can be selected in
// customizer. Instead of leaving the front and back open, walls can be
// generated for more stiffness.

// number of slots in a row
slots = 8;       // [1:1:25]
// slot diameter in mm from flat face to flat face
slot_size = 6.5;
// double sided
double_sided = 0; // [1:Yes, 0:No]

/* [Advanced] */
// distance in mm between first/last slot and end
distance_to_end = 2;
// distnace in mm between slots
distance_btw_slots = 1;
// height in mm of floor below slots
floor_height = 2;
// height in mm of the slot
slot_height = 8;

// thickness in mm of wall on the back side (0 to disable)
back_wall = 0;
// thickness in mm of wall on the front side (0 to disable)
front_wall = 0;

module bitholder()
{
    ri = slot_size/2; // inner circle radius of hexagon
    ru = ri*2/sqrt(3); // outter circle radius of hexagon
    // ri=3.25 ru=3.753

    cube_x = 2*distance_to_end+
    slots*(ru*2)+
    (slots-1)*distance_btw_slots;
    cube_y = ri*2*0.99;

    module hexagon(offset)
    {
        points = [[-ru+offset,0],
        [-ru/2+offset,ri],
        [ru/2+offset,ri],
        [ru+offset,0],
        [ru/2+offset,-ri],
        [-ru/2+offset,-ri]];
        polygon(points,[[0,1,2,3,4,5]]);
    }

    module slot_array()
    {
        difference() {
            translate([0,-cube_y/2-front_wall,-floor_height])
                cube([
            cube_x,
            cube_y+back_wall+front_wall,
            slot_height+floor_height
            ]);
            for (i=[0:slots-1]) {
                linear_extrude(10)
                    hexagon(ru+distance_to_end+
                i*(ru*2+distance_btw_slots));
            }
        }
    }

    slot_array();
    if (double_sided==1) {
        translate([0,0,-floor_height])
            mirror([0,0,1])
                slot_array();
    }

}

bitholder();

```


[User]
I'd like to create a customizable 2D origami papership design using OpenSCAD. I've got a basic idea and some parameters I want to control.

Here's the breakdown:

**Overall Shape:** The design is based on a series of connected polygons. The outer shape is defined by 8 points (A1-A8), and there are internal polygons that create the "folded" effect (C1-C8), defined using inner points (B1-B4).

**Customizable Parameters:**

*   **`max_size_in_millimeter`**: This determines the maximum size of the longest side of the model. The shorter side should scale proportionally to maintain the aspect ratio. It should have a reasonable range, say from 20mm to 300mm, with the default around 120mm.

*   **`model_height_in_millimeter`**: Sets the height of the 2D shape when extruded.  The range should be from 0.2mm up to 100mm, with a finer step of 0.2mm and a default of around 5mm.

*   **`outline_size_in_millimeter`**:  Specifies the thickness of the outer border/outline. I would like it to have a range of 0.5mm to 20mm, with a 0.1mm step and a default around 1.7mm.

*   **`inline_size_in_millimeter`**:  Determines the thickness of the internal outlines, same range, step and default as the outer outline, with a default around 0.7mm

*   **`inline_edge_radius_in_millimeter`**:  Controls the roundness of the edges of the internal outlines. A range of 0mm to 5mm with a step of 0.1mm and a default around 0.1mm would be useful.

*   **`flip_model`**: This should be a toggle ("yes" or "no") to mirror the model across the vertical axis. Default to "no".

**Key Design Features:**

*   The core of the design is an extruded shape.
*   I need the outer outline to be a border around the entire set of polygons.
*   The internal polygons need to be "cut out" with the defined line thickness using offsets and rounded edges.
*   The design needs to maintain aspect ratio, so if I change the max size, the other dimensions should adjust accordingly
*   The `$fn` variable for circle quality should be set to 32.

**Libraries:**
I don't think I'd need any external libraries for this.

Could you generate the OpenSCAD code for this, with these features?

[Assistant]
customizable_origami_papership.scad:
```
/*
 * Customizable Origami - Papership - https://www.thingiverse.com/thing:2622520
 * by Dennis Hofmann - https://www.thingiverse.com/mightynozzle/about
 * created 2017-11-03
 * 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.7; //[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.1; //[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 = [19, 69];
A2 = [480, 196];
A3 = [601, 78];
A4 = [619, 58];
A5 = [730, 232];
A6 = [1245, 114];
A7 = [957, 580];
A8 = [209, 580];

outline = [A1, A2, A3, A4, A5, A6, A7, A8];

// Inner Points
B1 = [480, 436];
B2 = [503, 431];
B3 = [341, 331];
B4 = [785, 305];

// Polygons
C1 = [B3, A2, A3, B1];
C2 = [B1, B2, A4, A3];
C3 = [A4, A5, B4, B2];
C4 = [A5, A6, B4];
C5 = [B2, B4, A6, A7, B1];
C6 = [B1, A7, A8];
C7 = [B1, B3, A1, A8];
C8 = [B3, A2, A1];

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

min_x = A1[0];
min_y = A4[1];
max_x = A6[0];
max_y = A7[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 parametric OpenSCAD model for a Dual In-line Package (DIP) integrated circuit, like the one I've described. The parameters need to include:

*   `nPinsIn`: The number of pins on the IC (note this should round up to an even number)
*   `icw`: Package width (middle section)
*   `ich1`: Package height (middle section)
*   `ich2`: Package height (top section)
*   `ich3`: Package height (bottom section)
*   `icec`: Package end cap depth
*   `t1`: Package top taper
*  `t2`: Package bottom taper
*   `pitch`: Pin pitch (spacing between pins)
*   `pinw1`: Pin lower section width
*   `pinw2`: Pin upper section width
*   `pinh2`: Pin upper section height
*   `pinh1`: Pin lower section height
*  `pino`: Pin offset from the package
*   `pint`: Pin thickness
*   `nh`: Notch depth
*   `nd`: Notch diameter
*   `hh`: Hole depth
*   `hd`: Hole diameter

The model should include the main body, the end caps, the pins, a notch, and a hole. The notch and hole are for indicating pin 1. The main body and end caps should be a sort of trapezoidal shape with a middle section. The pins should have a wider upper section and a narrower lower section. All parts should be defined in separate modules. The pin modules should use a mirroring technique, and the overall IC should use a loop to create a body composed of `ic_unit()` blocks, with mirrored endcaps on either end. Finally, I would like the parts colored 'DimGray' or 'Silver' as appropriate.

[Assistant]
ic.scad:
```
// DIP Package Integrated Circuit
// 2017-11-03
// Mike Zemba

// Parametrically generates a Dual In-line Package (DIP)
// integrated circuit (IC).

// ----------
// PARAMETERS
// ----------

    nPinsIn = 14;

    icw  = 5.588; // Package - Width (Middle Section)
    ich1 = 0.254; // Package - Middle Section Height
    ich2 = 1.625; // Package - Top Section Height
    ich3 = 1.625; // Package - Bottom Section Height
    icec = 0.75;  // Package - End Cap Depth
    t1   = 0.711; // Package - Taper (Top)
    t2   = 0.711; // Package - Taper (Bottom)

    pitch = 2.54; // Pin Pitch

    pinw1 = 0.558; // Pin - Lower Section Width
    pinw2 = 1.320; // Pin - Upper Section Width
    pinh2 = 2.667; // Pin - Upper Section Height
    pinh1 = 2.540; // Pin - Lower Section Height
    pino  = 1.016; // Pin - Offset from Package
    pint  = 0.254; // Pin - Thickness

    nh = 0.5; // Notch Depth
    nd = 1.5; // Notch Diameter

    hh = 0.2; // Hole Depth
    hd = 1;   // Hole Diameter

// Round Up # Pins If Odd (Must Be Even)
nPins = 2*ceil(nPinsIn/2);

difference(){
    union(){
        for (i=[0:1:nPins/2-1])
            translate([pitch*i,0,0])
                ic_unit();
        translate([-pitch/2-icec/2,0,0])
            ic_end(icec,icw,t1,t2,ich1,ich2,ich3);
        translate([pitch/2+pitch*(nPins/2-1)+icec/2,0,0])
            mirror([1,0,0])
                ic_end(icec,icw,t1,t2,ich1,ich2,ich3);
    }
    union(){
        translate([-pitch/2,0,ich2+ich1/2-nh])
            color("DimGray") cylinder(d=nd,h=nh+1,$fn=30);
        translate([0,-icw/5,ich2+ich1/2-hh])
            color("DimGray") cylinder(d=hd,h=hh+1,$fn=30);
    }
}

module ic_unit(){
    ic_body(pitch,icw,t1,t2,ich1,ich2,ich3);
    translate([0,icw/2+pint/2+pino,pint/2])
        pin(pinw1,pinw2,pinh1,pinh2,pint,pino);
    translate([0,-icw/2-pint/2-pino,pint/2])
        mirror([0,1,0])
            pin(pinw1,pinw2,pinh1,pinh2,pint,pino);
}

module ic_end(pitch,icw,t1,t2,ich1,ich2,ich3){
    // Top Polyhedron Points
    endTopPoints = [
    [pitch/2, icw/2, ich1/2],             // 0   +x +y
    [-pitch/2, icw/2, ich1/2],            // 1   -x +y
    [pitch/2, -icw/2, ich1/2],            // 2   +x -y
    [-pitch/2, -icw/2, ich1/2],           // 3   -x -y
    [pitch/2, icw/2-t1, ich1/2+ich2],     // 4   +x +y
    //[-pitch/2, icw/2-t1, ich1/2+ich2],    // 5   -x +y
    [pitch/2, -icw/2+t1, ich1/2+ich2]];    // 6   +x -y
    //[-pitch/2, -icw/2+t1, ich1/2+ich2]];  // 7   -x -y

    // Bottom Polyhedron Points
    endBotPoints = [
    [pitch/2, icw/2, -ich1/2],            // 0   +x +y
    [-pitch/2, icw/2, -ich1/2],           // 1   -x +y
    [pitch/2, -icw/2, -ich1/2],           // 2   +x -y
    [-pitch/2, -icw/2, -ich1/2],          // 3   -x -y
    [pitch/2, icw/2-t2, -ich1/2-ich3],    // 4   +x +y
    //[-pitch/2, icw/2-t2, -ich1/2-ich3],   // 5   -x +y
    [pitch/2, -icw/2+t2, -ich1/2-ich3]];   // 6   +x -y
    //[-pitch/2, -icw/2+t2, -ich1/2-ich3]]; // 7   -x -y

    endTopFaces = [
      [2,0,1,3],  // bottom
      [5,4,0,2],  // front
      [3,1,4,5],  // top
      [4,1,0],  // right
      [5,2,3]]; // left

    endBotFaces = [
      [2,0,1,3],  // bottom
      [5,4,0,2],  // front
      [3,1,4,5],  // top
      [4,1,0],  // right
      [5,2,3]]; // left

    color("DimGray") cube([pitch,icw,ich1],center=true);
    color("DimGray") polyhedron(endTopPoints,endTopFaces);
    color("DimGray") polyhedron(endBotPoints,endBotFaces);
}

module ic_body(pitch,icw,t1,t2,ich1,ich2,ich3){
    // Top Polyhedron Points
    topPoints = [
    [pitch/2, icw/2, ich1/2],             // 0   +x +y
    [-pitch/2, icw/2, ich1/2],            // 1   -x +y
    [pitch/2, -icw/2, ich1/2],            // 2   +x -y
    [-pitch/2, -icw/2, ich1/2],           // 3   -x -y
    [pitch/2, icw/2-t1, ich1/2+ich2],     // 4   +x +y
    [-pitch/2, icw/2-t1, ich1/2+ich2],    // 5   -x +y
    [pitch/2, -icw/2+t1, ich1/2+ich2],    // 6   +x -y
    [-pitch/2, -icw/2+t1, ich1/2+ich2]];  // 7   -x -y

    // Bottom Polyhedron Points
    botPoints = [
    [pitch/2, icw/2, -ich1/2],            // 0   +x +y
    [-pitch/2, icw/2, -ich1/2],           // 1   -x +y
    [pitch/2, -icw/2, -ich1/2],           // 2   +x -y
    [-pitch/2, -icw/2, -ich1/2],          // 3   -x -y
    [pitch/2, icw/2-t2, -ich1/2-ich3],    // 4   +x +y
    [-pitch/2, icw/2-t2, -ich1/2-ich3],   // 5   -x +y
    [pitch/2, -icw/2+t2, -ich1/2-ich3],   // 6   +x -y
    [-pitch/2, -icw/2+t2, -ich1/2-ich3]]; // 7   -x -y

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

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

    color("DimGray") cube([pitch,icw,ich1],center=true);
    color("DimGray") polyhedron(topPoints,topFaces);
    color("DimGray") polyhedron(botPoints,botFaces);
}

module pin(pinw1,pinw2,pinh1,pinh2,pint,pino) {
    translate([-pinw2/2,-pint/2,-pinh2])
        color("Silver") cube([pinw2,pint,pinh2],center=false);
    translate([-pinw1/2,-pint/2,-pinh2-pinh1])
        color("Silver") cube([pinw1,pint,pinh1],center=false);
    translate([-pinw2/2,-pint/2-pino,-pint])
        color("Silver") cube([pinw2,pino,pint]);
}

//translate([0,0,pinh1/2+pinh2/2])
//    cube([pinw2,pint,pinh2],center=true);
```


[User]
Hi there, I'm looking for some help creating a parametric design for a CPU delidding tool using OpenSCAD. I've already got a good idea of what I want, but I'm not great at the 3D modeling part.

The tool needs to consist of two main parts: a base and a cover. The base will hold the CPU and the cover will press down to separate the heat spreader (IHS) from the CPU PCB. I need to be able to adjust the dimensions of the tool based on different CPU sizes, so I need a good amount of parameters. I want to make this as generic as possible so it will work with any Intel processor that doesn't have a soldered IHS, so some parameters will need to be very flexible.

Here’s what I’m thinking for parameters:

**CPU Dimensions:**
*   `cpu_width`: Total width of the CPU's PCB.
*   `cpu_depth`: Total depth of the CPU's PCB.
*   `cpu_height`: Total height of the entire CPU (including the IHS).
*   `pcb_height`: Total height of just the PCB.
*   `lip_height`: Height of the lip (thin base) of the IHS.
*   `lip_depth`: Depth of the lip (thin base) on the IHS.
*   `lip_cutout`: Cutout width for the middle of some newer processors.

**Tool Margins:**
*   `width_margin`: Margin on the X sides of the tool (how much extra space there is on the side of the CPU).
*   `depth_margin`: Margin on the Y sides of the tool.
*   `height_margin`: Margin on the top and bottom of the tool.
*   `bottom_clearance`: Clearance for the components on the bottom of the CPU.
*   `bottom_margin`: Margin to the sides of the components on the bottom of the CPU.

**Other Parameters:**
*   `fillet_radius`: Radius for the rounded corners of the tool parts. This should be calculated as a function of the `height_margin` and the `depth_margin`.
*   `$fn`: Resolution for the curves and fillets.

For the base, I need a cutout for the PCB that matches the `cpu_width`, `cpu_depth`, and `pcb_height`. There needs to be a clearance area for the components on the bottom of the CPU (`bottom_clearance`) with a specified margin (`bottom_margin`). I also want it to have a rounded rectangular shape using the `roundcube` module (defined in the previous file).

The cover needs to have a rounded rectangle to match the base, and a lip to press on the edge of the IHS, so there should be a cutout for the IHS lip using `lip_height` and `lip_depth`, as well as a cutout for the middle of the IHS if needed, using `lip_cutout`. It should also have a flat top to apply pressure with a clamp.

I'd like a module to allow me to view only the base, only the cover, a full assembly, or the base and the cover separately. I also want to use a `roundcube` module that has a radius and can optionally be centered.

I'm not using any specific libraries and don't want to. I am okay with a single file for everything though.

I think that covers all the major points. Let me know if you have any questions. Thanks in advance!

[Assistant]
DELID-TOOL.scad:
```
// View the tool base, cover, or both.
part = "cover"; // [base:Base Only,cover:Cover Only,assembly:Full Assembly,both:Base and Cover]

print_part();

/* [CPU Dimensions] */

// Total width of the CPU's PCB.
cpu_width = 45;
// Total depth of the CPU's PCB.
cpu_depth = 42.5;
// Total height of the entire CPU (including the IHS).
cpu_height = 4.6;

// Total height of just the PCB.
pcb_height = 1.6;
// Height of the lip (thin base) of the IHS.
lip_height = 1.1;
// Depth of the lip (thin base) on the IHS.
lip_depth = 2.1;
// Cutout width for the middle of some new lake-generation processors.
lip_cutout = 0;

/* [Box Margins] */

// Margin on the X sides of the tool.
width_margin = 5; // [2:1:10]
box_width = cpu_width + width_margin * 2;
// Margin on the Y sides of the tool.
depth_margin = 5; // [2:1:10]
box_depth = cpu_depth + depth_margin * 3;
// Margin on the top and bottom of the tool.
height_margin = 5; // [2:1:10]
box_height = cpu_height + height_margin * 2;
// Clearance for the components on the bottom of the CPU.
bottom_clearance = 2; // [1:0.2:3]
// Margin to the sides of the components on the bottom of the CPU.
bottom_margin = 20; //[2:1:10]

/* [Hidden] */

// Resolution quality of the curves and fillets.
$fn = 30;

cover_height = cpu_height - pcb_height;
fillet_radius = (height_margin + depth_margin) / 4;

// Make a cube with four rounded sides.
module roundcube(xyz, r, center=false) {
    translate(center ? -[xyz[0] / 2, xyz[1] / 2, xyz[2] / 2] : []) hull() {
        translate([r,          r,          0]) cylinder(h=xyz[2], r=r);
        translate([r,          xyz[1] - r, 0]) cylinder(h=xyz[2], r=r);
        translate([xyz[0] - r, r,          0]) cylinder(h=xyz[2], r=r);
        translate([xyz[0] - r, xyz[1] - r, 0]) cylinder(h=xyz[2], r=r);
    }
}

// Total geometry of the tool base.
module print_base() {
    difference() {
        // The main cube to cut from.
        rotate([90]) roundcube([box_width, box_height, box_depth], fillet_radius, center=true);

        // Large section on top, half cube.
        translate([0, depth_margin / 2 + 0.5, box_height / 4 + 0.5])
            cube([cpu_width, cpu_depth + depth_margin * 2 + 1, box_height / 2 + 1], center=true);

        // PCB cutout.
        translate([0, depth_margin / 2, -pcb_height / 2 + 0.5])
            cube([cpu_width, cpu_depth, pcb_height + 1], center=true);

        // Bottom components clearance.
        translate([0, depth_margin / 2, -pcb_height / 2 - bottom_clearance / 2 + 0.5])
            cube([cpu_width - bottom_margin * 2, cpu_depth - bottom_margin * 2, bottom_clearance + 1], center=true);
    }
}

// Total geometry of the tool cover.
module print_cover() {
    // translate([0, -depth_margin])
    union() {
        // Round cube for the front part.
        translate([0, box_depth / 2 + depth_margin / 2]) rotate([90])
            roundcube([box_width, box_height, depth_margin], fillet_radius, center=true);

        difference() {
            // Filleted cube for the part pressuring the IHS.
            translate([0, box_depth / 2 - depth_margin * 1.5 - lip_depth / 2, -cover_height]) hull() {
                translate([ cpu_width / 2 - cover_height, 0, 0]) rotate([90])
                    cylinder(r=cover_height, h=depth_margin * 3 + lip_depth, center=true);
                translate([-cpu_width / 2 + cover_height, 0, 0]) rotate([90])
                    cylinder(r=cover_height, h=depth_margin * 3 + lip_depth, center=true);
            }

            // Cutout for the IHS lip.
            translate([0, -lip_depth / 2 + box_depth / 2 - depth_margin * 3 - 0.5, -lip_height / 2 + 0.5])
                cube([cpu_width, lip_depth + 1, lip_height + 1], center=true);

            // Cutout in the middle for some newer processors.
            translate([0, -lip_depth / 2 + box_depth / 2 - depth_margin * 3 - 0.5, -cover_height / 2 + 0.5])
                cube([lip_cutout, lip_depth + 1, cover_height + 1], center=true);
        }

        // Main top part of the cover.
        translate([0, depth_margin / 2, -box_height / 4 - cover_height / 2])
            cube([cpu_width, box_depth - depth_margin, box_height / 2 - cover_height], center=true);
    }
}

// Select the part to calculate by the part variable.
module print_part() {
    if (part == "base") { // View tool base.
        print_base();
    } else if (part == "cover") { // View tool cover.
        print_cover();
    } else if (part == "assembly") { // View tool assembly.
        color([1, 1, 0, 0.5]) translate([0, -depth_margin / 2]) print_base();
        color([0, 1, 1, 0.5]) translate([0,  depth_margin / 2]) rotate([0, 180]) print_cover();
    } else { // View tool spread out, printable form. Includes both option.
        translate([-box_width / 2 - 5, 0 / 2, 0]) print_base();
        translate([ box_width / 2 + 5, 0,     0]) print_cover();
    }
}

```


[User]
I'd like to create a customizable 2D origami squirrel design using OpenSCAD. The design should be based on the provided points and polygons, allowing for adjustments to size and thickness.

Specifically, I need:

*   A main outline defined by points A1 through A21.
*   Inner cut shapes defined by polygons C1 through C12, which use some of the same points and some new points B1 through B5.
*   The ability to set a maximum size for the longest side of the squirrel, with the other side scaling proportionally.
*   A separate setting for the model's height.
*   Adjustable thicknesses for both the outer outline and the inner cut lines.
*   A way to control the roundness of the inner cut line ends.
*   An option to flip the model horizontally.

The overall approach should be to create the basic shape, then subtract the inner cut shapes from that outer shape. I want to be able to set the size such that the largest dimension matches the `max_size_in_millimeter` parameter, and the model should be centered. I'd also want to be able to flip it to face the other direction using a `flip_model` parameter, and also adjust the `model_height_in_millimeter`. The parameters `outline_size_in_millimeter`, `inline_size_in_millimeter` and `inline_edge_radius_in_millimeter` should be used to control the rendering of the outer outline, inner outline and edge roundness, respectively.

[Assistant]
customizable_origami_squirrel.scad:
```
/*
 * Customizable Origami - Squirrel - https://www.thingiverse.com/thing:2625230
 * by Dennis Hofmann - https://www.thingiverse.com/mightynozzle/about
 * created 2017-11-04
 * 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.7; //[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 = [388, 152];
A2 = [513, 278];
A3 = [514, 336];
A4 = [646, 223];
A5 = [644, 142];
A6 = [682, 104];
A7 = [706, 143];
A8 = [863, 226];
A9 = [849, 263];
A10 = [736, 283];
A11 = [813, 328];
A12 = [724, 357];
A13 = [724, 483];
A14 = [668, 579];
A15 = [753, 634];
A16 = [635, 634];
A17 = [493, 634];
A18 = [331, 446];
A19 = [203, 332];
A20 = [186, 215];
A21 = [196, 103];

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

// Inner Points
B1 = [456, 290];
B2 = [395, 443];
B3 = [458, 444];
B4 = [461, 422];
B5 = [664, 378];

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

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

min_x = A20[0];
min_y = A21[1];
max_x = A8[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]
Okay, I need a parametric design in OpenSCAD for a webcam mount, specifically for a Trust SpotLight Webcam, that will attach to a 3D printer, like the German RepRap NEO. I've got a basic idea of what I want but it needs to be easily customizable for different printer setups.

The design should consist of two main parts: a printer mount and a webcam adapter. The printer mount should have a flat surface to attach to the printer frame with a through hole for a screw. The webcam adapter should have a circular base that fits into a hole on the mount and a vertical arm to hold the webcam, and a hole to receive a screw coming out of the bottom of the webcam.

Here are the main parameters I want to control:

*   **wiggle**: This should be a small value that adds some tolerance for printing inaccuracies, affecting the sizes of holes and clearances. It should be applied universally. Something like 0.25mm would be good.
*   **mount_thickness**: The thickness of the printer mount's base.
*   **mount_width**: The width of the printer mount's base.
*    **mount_height**: The height of the printer mount's base.
*   **mount_hole_diameter**: The diameter of the hole in the printer mount for the mounting screw.
*   **adapter_diameter**: The diameter of the circular base of the webcam adapter that fits into the mount.
*   **adapter_thickness**: The thickness of the circular base of the webcam adapter.
*   **adapter_arm_height**: The height of the vertical arm that holds the webcam.
*   **adapter_screw_diameter**: The diameter of the hole in the arm of the webcam adapter that will hold the webcam screw.
*   **adapter_screw_counterbore**: The diameter of the larger hole in the arm of the webcam adapter that will accommodate the head of the webcam screw.
*   **webcam_screw_offset**: How much the webcam screw hole is offset from the center of the circular base.

I'd also like to have a parameter for the overall height the webcam is mounted above the printer mounting base, measured from the screw hole.

The mounting screw for the printer should be an M4, as should the screw hole in the adapter for the webcam.

Could you create a parametric OpenSCAD file that uses these parameters to create the mount and adapter? I'd like to be able to adjust all of these dimensions. I don't need any special libraries, just the base OpenSCAD primitives.

[Assistant]
Webcam_Holder_V4.scad:
```
//Set the wiggle room around things to cope with non-exact prints
wiggle=0.25;

//moving webcam down by 15mm measured from screw
heigt_from_screw=15;

/* [Hidden] */
//----------------------------------------------------------------------------

$fn=20;

thick=9.8-1.5*wiggle;
rotation_free=0.5;
wide=10.7-2*rotation_free;
holedia=4+2*wiggle;
length=wide+1;
height=heigt_from_screw;

wc_screw=5+2*wiggle;
wc_hole=4+wiggle;
wc_wall=1.5+wiggle;

difference()
{
    union()
        {
            cylinder(d=wide,h=thick);

            translate([-wide/2,0,0])
                cube([wide,height,thick]);

            *hull()
            {
                translate([-wide/2,0,0])
                    cube([wide,0.1,thick]);
                translate([0,height,wide/2])
                    rotate([90,0,0])
                        cylinder(d=wide,h=.5);
            }
        }

    translate([0,0,-wiggle])
        cylinder(d=holedia,h=thick+2*wiggle);

    //mounting screw hole
    translate([0,-wide/2-wc_wall,thick/2])
        rotate([-90,0,0])
            cylinder(d=wc_screw,h=wide/2+height);

    translate([0,-wide/2+1,thick/2])
        rotate([-90,0,0])
            cylinder(d=wc_hole,h=wide/2+height);
}

```


[User]
I'd like to create a customizable origami panther head design using OpenSCAD. The base of the design is defined by a series of 2D coordinates which define the outline and inner cut shapes.

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

*   **`max_size_in_millimeter`**: This should control the overall size of the design, with the shorter side being automatically resized proportionally. Let's say the range for this parameter should be from 20 to 300mm.

*   **`model_height_in_millimeter`**: This controls the thickness of the extruded design, ranging from 0.2 to 100mm in 0.2mm increments.

*   **`outline_size_in_millimeter`**: This parameter should control the thickness of the outer outline, and I'd like to vary this from 0.5mm to 20mm, with a step size of 0.1mm.

*   **`inline_size_in_millimeter`**: This sets the thickness of the inner outlines. The same ranges apply as above; from 0.5 to 20, with a step of 0.1mm.

*   **`inline_edge_radius_in_millimeter`**:  This parameter will control how rounded the inner outlines are, allowing a range from 0 to 5mm with 0.1mm increments.

*   **`flip_model`**: This will be a string variable taking either the value "yes" or "no". If "yes", the design will be flipped along the y-axis, and then rotated 180 degrees in X and Y. If "no", the model is displayed without any transformation.

The design itself is defined by the following 2D coordinates (I'll provide the raw coordinate points, in case it is easier to parse):

```
// Outer Points
A1 = [400, 35];
A2 = [526, 73];
A3 = [581, 42];
A4 = [622, 9];
A5 = [671, 32];
A6 = [681, 77];
A7 = [615, 225];
A8 = [641, 371];
A9 = [595, 481];
A10 = [543, 526];
A11 = [498, 586];
A12 = [455, 648];
A13 = [352, 648];
A14 = [303, 588];
A15 = [257, 529];
A16 = [205, 481];
A17 = [159, 369];
A18 = [186, 224];
A19 = [117, 75];
A20 = [127, 32];
A21 = [175, 9];
A22 = [217, 44];
A23 = [273, 74];

// Inner Points
B1 = [248, 493];
B2 = [269, 435];
B3 = [295, 404];
B4 = [552, 493];
B5 = [505, 404];
B6 = [527, 432];
B7 = [274, 266];
B8 = [273, 291];
B9 = [308, 303];
B10 = [324, 290];
B11 = [399, 315];
B12 = [476, 291];
B13 = [527, 266];
B14 = [526, 291];
B15 = [495, 303];
B16 = [333, 455];
B17 = [363, 450];
B18 = [436, 449];
B19 = [465, 456];
B20 = [378, 499];
B21 = [400, 558];
B22 = [421, 499];
B23 = [342, 584];
B24 = [456, 583];
B25 = [229, 305];
B26 = [570, 302];

// Polygons
C1 = [A18, A23, A22, A21, A20, A19];
C2 = [A2, A3, A4, A5, A6, A7];
C3 = [A23, A1, A2, B12, B11, B10];
C4 = [B12, A2, A7, B13];
C5 = [A23, B10, B7, A18];
C6 = [A18, B25, B7];
C7 = [A18, B25, A17];
C8 = [B25, B2, A17];
C9 = [B11, B17, B18];
C10 = [B18, B19, B12, B11];
C11 = [B11, B17, B16, B10];
C12 = [B20, B22, B21];
C13 = [B16, B17, B18, B19, B22, B20];
C14 = [A14, B23, B21, B24, A11, A12, A13];
C15 = [B24, A11, A10, B4, B6, B5, B12, B19, B22, B21];
C16 = [B10, B3, B2, B1, A15, A14, B23, B21, B20, B16];
C17 = [B2, B3, B10, B9, B8, B7, B25];
C18 = [B12, B5, B6, B26, B13, B14, B15];
C19 = [B13, B26, A7];
C20 = [B26, A7, A8];
C21 = [A8, B26, B6];
C22 = [B12, B15, B14, B13];
C23 = [B7, B8, B9, B10];
C24 = [A8, B4, A10, A9];
C25 = [B4, B6, A8];
C26 = [A15, B1, A17, A16];
C27 = [A17, B1, B2];

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, C26, C27];
```

I'd expect the code to calculate the proper scaling factor based on the given max size, ensure proper resizing, and correctly render the model in the requested orientation based on the `flip_model` setting. Also, the inner outline should be rounded by the inline_edge_radius value, and this value should be scaled appropriately depending on whether the model is scaled based on width or height. Let me know if you need more information.

[Assistant]
customizable_origami_panther_head.scad:
```
/*
 * Customizable Origami - Panther Head - https://www.thingiverse.com/thing:2626257
 * by Dennis Hofmann - https://www.thingiverse.com/mightynozzle/about
 * created 2017-11-04
 * 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.7; //[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 = [400, 35];
A2 = [526, 73];
A3 = [581, 42];
A4 = [622, 9];
A5 = [671, 32];
A6 = [681, 77];
A7 = [615, 225];
A8 = [641, 371];
A9 = [595, 481];
A10 = [543, 526];
A11 = [498, 586];
A12 = [455, 648];
A13 = [352, 648];
A14 = [303, 588];
A15 = [257, 529];
A16 = [205, 481];
A17 = [159, 369];
A18 = [186, 224];
A19 = [117, 75];
A20 = [127, 32];
A21 = [175, 9];
A22 = [217, 44];
A23 = [273, 74];

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

// Inner Points
B1 = [248, 493];
B2 = [269, 435];
B3 = [295, 404];
B4 = [552, 493];
B5 = [505, 404];
B6 = [527, 432];
B7 = [274, 266];
B8 = [273, 291];
B9 = [308, 303];
B10 = [324, 290];
B11 = [399, 315];
B12 = [476, 291];
B13 = [527, 266];
B14 = [526, 291];
B15 = [495, 303];
B16 = [333, 455];
B17 = [363, 450];
B18 = [436, 449];
B19 = [465, 456];
B20 = [378, 499];
B21 = [400, 558];
B22 = [421, 499];
B23 = [342, 584];
B24 = [456, 583];
B25 = [229, 305];
B26 = [570, 302];

// Polygons
C1 = [A18, A23, A22, A21, A20, A19];
C2 = [A2, A3, A4, A5, A6, A7];
C3 = [A23, A1, A2, B12, B11, B10];
C4 = [B12, A2, A7, B13];
C5 = [A23, B10, B7, A18];
C6 = [A18, B25, B7];
C7 = [A18, B25, A17];
C8 = [B25, B2, A17];
C9 = [B11, B17, B18];
C10 = [B18, B19, B12, B11];
C11 = [B11, B17, B16, B10];
C12 = [B20, B22, B21];
C13 = [B16, B17, B18, B19, B22, B20];
C14 = [A14, B23, B21, B24, A11, A12, A13];
C15 = [B24, A11, A10, B4, B6, B5, B12, B19, B22, B21];
C16 = [B10, B3, B2, B1, A15, A14, B23, B21, B20, B16];
C17 = [B2, B3, B10, B9, B8, B7, B25];
C18 = [B12, B5, B6, B26, B13, B14, B15];
C19 = [B13, B26, A7];
C20 = [B26, A7, A8];
C21 = [A8, B26, B6];
C22 = [B12, B15, B14, B13];
C23 = [B7, B8, B9, B10];
C24 = [A8, B4, A10, A9];
C25 = [B4, B6, A8];
C26 = [A15, B1, A17, A16];
C27 = [A17, B1, B2];

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, C26, C27];

min_x = A19[0];
min_y = A4[1];
max_x = A6[0];
max_y = A13[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 an OpenSCAD design for a fruit fly trap lid that fits onto a standard baby food jar. I've got some basic dimensions for the jar that I've already measured, and I want to be able to adjust them if needed, so it should be parametric. I'd like the design to be in multiple files, and not one huge file - you know, good practice.

Here are the jar dimensions:

*   **Jar Inner Diameter:** 43.2 mm
*   **Jar Thread Diameter:** 48.6 mm
*   **Jar Thread Height:** 5.2 mm

I'd like the lid to have a flat top, then a section that matches the jar's threads so it screws on, and finally, a cone-shaped funnel that goes down into the jar with a small hole in the center. This funnel will help funnel the flies inside.

Here are some additional design requirements and some ideas I have:

*   **Funnel Height:** The height of the cone should be adjustable but I was thinking about 20mm.
*   **Hole Diameter:** The hole at the bottom of the funnel should be something I can change, about 3mm would work for now.
*   **Wall Thickness:** The general wall thickness of the lid should be about 1mm.
*   **File Structure:** I want to break down the code into separate files. I'm thinking:
    *   `constants.scad` which just defines all the adjustable measurements
    *   `shapes.scad` which has a `cleanRail()` function. It should create a "rail" (like a thin rectangle with rounded ends) between any two points, with a specified thickness.
    *   `main.scad` which uses the functions in the other files to create the overall fruit fly trap lid design using rotate_extrude().
*   **Library:** I don't think this would need any particular libraries

Can you generate the files for this design?

[Assistant]
FruitFlyTrap.scad:
```
/*
Fruit fly trap

George Miller
11-03-2017

This will be sized to fit onto a baby food jar.
*/

JarInnerDia=43.2;
JarThreadDia=48.6;
JarThreadHeight=5.2;
coneHeight=20;
holeDia=3;
wallthick=1;

/* Hidden */
JIR=JarInnerDia/2;
JTR=JarThreadDia/2;
HoleR=holeDia/2;
PartOR = JTR+wallthick;
PartH = JarThreadHeight+wallthick;
/* Part */

$fn=180;
rotate_extrude()
{
    //flat lid
    CleanRail(X1=JIR-(wallthick/2),Y1=(wallthick/2),X2=PartOR-(wallthick/2),Y2=(wallthick/2),Width=wallthick);

    //lid thread and rim
    //translate([JTR,0,0])
    //square([wallthick,PartH]);
    CleanRail(X1=PartOR-(wallthick/2),Y1=PartH-(wallthick/2),X2=PartOR-(wallthick/2),Y2=(wallthick/2),Width=wallthick);

    //funnel
    CleanRail(X1=JIR-(wallthick/2),Y1=(wallthick/2),X2=HoleR+(wallthick/2),Y2=coneHeight-(wallthick/2),Width=wallthick);

}

//CleanRail();
module CleanRail(X1=0,Y1=0,X2=20,Y2=20,Width=2){
    //puts a rail between two points.
    Q1 = (X2>=X1)&&(Y2>=Y1)?atan((Y2-Y1)/(X2-X1)):0;
    Q2 = (X2<X1)&&(Y2>=Y1)?(180+atan((Y2-Y1)/(X2-X1))):0;
    Q3 = (X2<X1)&&(Y2<Y1)?(180+atan((Y2-Y1)/(X2-X1))):0;
    Q4 = (X2>=X1)&&(Y2<Y1)?(atan((Y2-Y1)/(X2-X1))):0;
    //angle = atan((Y2-Y1)/(X2-X1)) + Q1 + Q2 + Q3 + Q4;
    angle = Q1 + Q2 + Q3 + Q4;
    //rad = round(angle/90)==(angle/90)?0:(Width/2);
    rad = (Width/2);
    length = sqrt(pow((X2-X1),2)+pow((Y2-Y1),2));

    translate([X1,Y1,0])
    union(){
        rotate([0,0,angle])
        translate([0,0,0]){
            circle(rad,$fn=45);
            translate([0,-(Width/2),0])
            square([length,Width]);
            translate([length,0,0])
            circle(rad,$fn=45);
        }
    }

}
```


[User]
I'm looking to design a forearm gauntlet for rowing machine use, specifically for someone with limited hand mobility. I have some existing code that gives you an idea of what I'm going for, but I need a design that's more robust and customizable.

Here's a breakdown of what I need:

*   **Core Gauntlet:** The main structure should be a sort of curved, open-ended cuff that wraps around the forearm. It should have variable dimensions to accommodate different forearm sizes.
*   **Forearm Length:** The length of the gauntlet needs to be adjustable; I'm imagining it's defined by a distance from the wrist to the elbow crease.
*   **Circumference:** I need the circumference of the device to be adjustable at both the top (near the elbow) and the bottom (near the wrist). Since the forearm isn't a perfect cylinder, I'm assuming the circumference at the top will be a bit larger than at the bottom. I need to be able to set both separately.
*   **Device Length:** This is the total length of the device, and will be a percentage of the forearm length. The device should sit somewhere between 15% and 85% of the forearm length. It should be adjustable.
*   **Wraparound:** The amount the top and bottom of the device wraps around the forearm should be adjustable using a percentage of the circumference.
*   **Thickness:** The thickness of the material of the gauntlet should be adjustable.
*   **Attachment Point:** I need to include a cylindrical tube at the front of the device that can be used as an attachment point for a rowing machine handle. I need to be able to specify the diameter of this tube. This needs to be placed forward of the device, the placement distance must be adjustable.
*   **Slot System:** Finally, I need a series of parallel slots along the edges of the device for strapping or additional attachments. I need to be able to adjust the slot offsets, and how many slots are placed along the edges.

I'd like all these features to be parametrically adjustable using OpenSCAD. My goal is to create a design that can be easily modified for individual users.  I'd prefer to avoid using an excessive amount of `for` loops; please try to make the code as efficient as possible.

Could you please generate the OpenSCAD file(s) for this design, and be sure to use the `BOSL2` library? Please let me know if you have any questions.

[Assistant]
Forearm_Gauntlet_Para.scad:
```
// - Wrist Joint to Elbow Crease (mm) (Default = 210)
ForearmLen = 210; //[150:380]
// - Upper Forearm Circumference (mm) (85%) (Default = 194)
UpForearmCircum = 194; //[110:360]
// - Bot Forearm Circumference (mm) (15%) (Default = 142)
BotForearmCircum = 142; //[110:360]
// - Device Thickness (mm) (Default = 5)
Thickness = 5; //[4,5,6]
// - Tube Diameter (mm)
TubeDiameter = 2; //[1.5,2,2.5]

/* [Hidden] */
//Select Device Length of Forearm (70% Default)
ForearmPerc = 0.7;
//Device sits on 15% to 85%
DeviceLength = ForearmLen * ForearmPerc;

//Percent Upper Part wraps arounf Forearm
UpForearmPerc = .42;
UpDeviceWidth = UpForearmCircum * UpForearmPerc;

//Percent Bottom Part wraps around Forearm
BotForearmPerc = .33;
BotDeviceWidth = BotForearmCircum * BotForearmPerc;

module Forearm(){
    translate ([0,0,Thickness / 2])
    linear_extrude (height = Thickness, center = true, convexity = 10, rotate = 0, twist = 0, slices = 20, scale = 1.0)
    polygon(points = [
    [(-1 * (UpDeviceWidth * 0.5)),(0 + DeviceLength / 2)], //Top Left
    [(UpDeviceWidth * 0.5),(0 + DeviceLength / 2)], //Top Right
    [(BotDeviceWidth * 0.5), (0 - DeviceLength / 2)], //Bottom Right
    [(-1 * (BotDeviceWidth * 0.5)), (0 - DeviceLength / 2)] //Bottom Left
    ],
    paths = [[0,1,2,3]]);
}

module Tube(){
    if (ForearmLen < 250){CircOff =10;
        rotate_extrude(convexity = 10)
        translate([((DeviceLength / 2) + CircOff - 15), Thickness / 2, 0])
        circle(r = (TubeDiameter / 2), $fn = 100);
    }
    else { CircOff = 0;
        rotate_extrude(convexity = 10)
        translate([((DeviceLength / 2) + CircOff - 15), Thickness / 2, 0])
        circle(r = (TubeDiameter / 2), $fn = 100);
    }
}

module rightSlots(){
    x2 = (UpDeviceWidth * 0.5);
    x1 = (BotDeviceWidth * 0.5);
    y2 = (0 + DeviceLength / 2);
    y1 = (0 - DeviceLength / 2);
    RAngle = atan2((y2-y1), (x2-x1));

    rotate([0,0,270 + RAngle])
    for (slotOff = [-DeviceLength * 0.4: 30 : DeviceLength *0.25  ]){
        translate([BotDeviceWidth * 0.5, slotOff, -Thickness / 2])
        union(){
                cube([4.5,20, Thickness + 30]);
                translate([2.25, 0, 0]) cylinder(r = 2.25, h = Thickness + 30);
                translate([2.25, 20, 0]) cylinder(r = 2.25, h = Thickness + 30);
        }
    }
}

module leftSlots(){
    x2 = (-UpDeviceWidth * 0.5);
    x1 = (-BotDeviceWidth * 0.5);
    y2 = (0 - DeviceLength / 2);
    y1 = (0 + DeviceLength / 2);
    LAngle = atan2((y2-y1), (x2-x1));

    rotate([0,0,270 - LAngle])
    for (slotOff = [-DeviceLength * 0.4  : 30: DeviceLength * 0.25]){
        translate([-BotDeviceWidth * 0.55, slotOff, -Thickness / 2])
        union(){
                cube([4.5,20, Thickness + 30]);
                translate([2.25, 0, 0]) cylinder(r = 2.25, h = Thickness + 30);
                translate([2.25, 20, 0]) cylinder(r = 2.25, h = Thickness + 30);
        }
    }
}

difference(){
    Forearm();
    rightSlots();
    leftSlots();
    difference(){
        Tube();
        translate( [-150, -300, 0]) cube(300);
    }

}

```


[User]
Okay, I'm looking to design a spool roller, and I'd like it to be parametric so I can easily adjust it later. I've seen some designs out there, but I want to make sure I can tweak the specific dimensions to suit my needs exactly.

Here are the key features and dimensions I need:

*   **Bearings:** The design should use four bearings. The crucial dimensions for these are:
    *   `bearing_outer_d`: The outer diameter of the bearing. I'll probably start with a value of 13mm, but this needs to be adjustable.
    *   `bearing_inner_d`: The inner diameter of the bearing, which should be parametric (start with 4mm).
    *   `bearing_width`: The width of the bearing (start with 5mm).

*   **Bearing Placement:**
    *   `bearings_span`: This is the distance between the centers of the two bearings on each side of the roller. I'll likely want this to be around 80mm initially.
    *   The bearings should be inserted into recesses within the roller. There should be some clearance so the bearings fit snugly but aren't overly tight.

*   **Screws and Nuts:** The assembly will need to use M3 screws and nuts.
    *   `screw_length`: The length of the screw (start with 10mm).
    *   The design should incorporate recesses for the screw heads and nuts.
    *   I'd like the design to accommodate standard hex nuts, including the flats. I may want to switch the type of nut later, so the hole for the nut should be parameterized.
    *   `screw_d`: screw diameter, starting at 3mm.
    *   `screw_hd`: screw head diameter, starting at 6mm.
    *   `screw_hh`: screw head height, starting at 3mm.

*   **Overall Structure:**
    *   The roller needs to have a rigid structure connecting the bearings on each side.
    *   The central section should have a 'cutout' for material saving and aesthetics. The shape of this cutout needs to be parametric and should be some kind of triangular shape.
    *   I need to ensure that the design is printable without supports, as much as possible. The overall shape should be pretty robust, without too many overhangs. I anticipate a 0.2mm layer height, a 0.5 extrusion width, with an epsilon of 0.01.

*  **Modularity:** Please ensure that the design parameters are clearly defined and grouped, so it's straightforward to modify them later through the OpenSCAD customizer.

I think that covers all the requirements. Could you generate the OpenSCAD file(s) for this? I'm familiar with the basics of OpenSCAD, so you can assume I know things like `translate`, `rotate`, `cube`, `cylinder`, `difference`, and `union`. I don't need explanations for every basic command but please use well-named parameters. I am not looking to use any libraries other than the built-in ones of OpenSCAD. I don't really need any modules to keep the code more readable - a single file will be okay for this. I also don't need any comments explaining the units.

[Assistant]
spool-roller.scad:
```
/* Main */
// (in mm)
bearing_outer_d = 13;
// (in mm)
bearing_inner_d = 4;
// (in mm)
bearing_width = 5;

// The distance between two bearings (in mm)
bearings_span = 80;

// (in mm)
screw_length=10;

/* [Hidden] */
layer_height=.2; extrusion_width=.5;
epsilon=.01;

module spool_roller(
 b_od=bearing_outer_d,					// bearing outer diameter
 b_id=bearing_inner_d,					// bearings inner diameter
 b_h=bearing_width,					// bearing dimensions
 b_iod=bearing_inner_d+2,				// bearing inner ring outer diameter
 b_span=bearings_span,					// distance between bearings
 b_rclearance=2,					// bearing radial clearance
 b_aclearance=1,					// bearing axial clearance
 screw_l=screw_length,					// screw length
 screw_d=3,						// screw diameter
 screw_hd=6,						// screw head diameter
 screw_hh=3,						// screw head height
 nut_d = 5.45/cos(30),					// nut diameter
 nut_h = 2.5						// nut height
) {
 it = b_h+b_aclearance;     // inner thickness
 ot = screw_l+screw_hh;     // outer thickness
 s = (ot-it)/2;             // shell thickness
 osr = b_od/2+b_rclearance; // outer shell radius
 bs = s;                    // bottom shell
 cuto = osr/4;
 cutr = (cuto*cuto+b_span*b_span/4-osr*osr)/(osr+cuto)/2;
 difference() {
  union() {
   for(sx=[-1,1])
    translate([sx*b_span/2,0,bs+osr]) rotate([90,0,0])
    cylinder(r=osr,h=ot,center=true,$fn=osr*PI*4);
   translate([-b_span/2-osr,-ot/2,0])
   cube(size=[b_span+2*osr,ot,bs+osr+epsilon]);
   rotate([90,0,0])
   linear_extrude(height=ot,center=true)
   translate([0,bs]) polygon([
    [-b_span/2, osr],
    [ 0, cutr+osr-cuto],
    [ b_span/2, osr]
   ]);
   lh = layer_height*2;
   hull() {
    ro=3;
    linear_extrude(height=lh)
    offset(r=ro,$fn=4*PI*ro) offset(r=-ro,$fn=4*PI*ro)
    square(size=[b_span+2*osr+2*bs-2*lh,ot+2*bs+2*lh],center=true);
    translate([0,0,bs/2+epsilon/2])
    cube(size=[b_span+2*osr,ot,bs+epsilon],center=true);
   }
  }//union
  // big cutout
  translate([0,0,bs+cutr+osr-cuto]) rotate([90,0,0])
  cylinder(r=cutr,h=ot+2,center=true,$fn=cutr*PI*4);
  // spool cutout
  difference() {
   translate([-b_span/2-osr-1,-it/2,bs])
   cube(size=[b_span+2*osr+2,it,2*osr+1]);
   for(my=[0,1]) mirror([0,my,0])
   for(sx=[-1,1])
   translate([sx*b_span/2,it/2-b_aclearance/2,bs+osr])
   rotate([-90,0,0])
   cylinder(d1=b_iod,d2=b_iod+2*b_aclearance,h=b_aclearance,$fn=(b_iod+b_aclearance)*PI*2);
  }
  // screwholes
  for(mx=[0,1]) mirror([mx,0,0])
  translate([b_span/2,0,bs+osr]) {
   translate([0,-ot/2+screw_hh,0]) rotate([90,0,0])
   cylinder(d=screw_hd,h=screw_hh+1,$fn=screw_hd*PI*2);
   translate([0,ot/2-nut_h,0]) rotate([-90,0,0])
   rotate([0,0,30]) cylinder(d=nut_d,h=nut_h+1,$fn=6);
   rotate([90,0,0])
   cylinder(d=screw_d,h=ot+2,center=true,$fn=screw_d*PI*2);
  }
 }//difference
 // bearings
 % for(sx=[-1,1]) {
  translate([sx*b_span/2,0,bs+osr]) rotate([90,0,0])
  difference() {
   cylinder(d=b_od,h=b_h,center=true,$fn=b_od*PI*2);
   cylinder(d=b_id,h=b_h+2,center=true,$fn=b_id*PI*2);
  }
 }
}

spool_roller();

```


[User]
I'd like a custom phone case for a OnePlus 3, and I have some specific ideas about how it should work. I want it to be a parametric design in OpenSCAD, so I can tweak the dimensions and features later.

Here's what I'm thinking:

The core of the design should be a "bumper" style case, that fits around the phone. This base case needs to be flexible material as the model will be printed in TPU (95A). The overall dimensions need to be driven from a phone dimension parameter (x, y, and z). I also need a parameter that lets me add or subtract a small amount to each dimension to account for printing tolerances. This is important since I'll be using a flexible material, so I may need a slightly tighter fit (or looser fit for more flexible materials). The case should have cutouts for the volume buttons/alert slider, the power button, the USB/headphone/speaker area on the bottom, and the camera on the back. The camera cutout needs to have rounded corners, specifically using a minkowski sum to do this. The phone itself is rounded, so the phone case should incorporate a similar rounded edge. The sides of the case (the "caseSideThickness") should have a different wall thickness value than the top and bottom of the case (caseTopBottomThickness).

On top of the bumper case, I want to have options for a "wallet" style case, or a simpler top cover. If I go with the wallet style, it should have a "hinge" connecting the top part of the case to the bottom/bumper case, allowing it to flip open. The hinge should also have configurable thickness, and the x offset can be adjusted. For the hinge itself I'd just like a simple block. The wallet part should have a parameter for the number of credit card pockets, each with an air gap between layers. This means I need to add a parameter for the number of air gap layers. The credit card pockets should have a configurable top thickness too, and they should be positioned with an offset. There should also be a parameter to control how much extra vertical spacing there is between each credit card pocket. There should also be a parameter for the pocket itself having a thickness. I want to be able to also configure a separate top pocket without credit card pockets, and control how many layers that top pocket is.

Additionally, there needs to be a parameter to control the overall height of the top without credit card pockets. This parameter should be zero for a simple top cover, like a bumper case.

Finally, I'd like to have a way to engrave text into the top of the case using the `text` module. The text should be a configurable parameter, along with size, spacing, position, and font. The text needs to have configurable depth.

I'm looking to use the `minkowski()`, `hull()`, and `linear_extrude()` modules.

Could you generate this as a parametric OpenSCAD design?

[Assistant]
oneplus3_wallet_case.scad:
```
// Author: Christian Petry
// Designed in Switzerland 2017
// Version: 1.4 (2017-12-12)

/* Version History
V1.0 (2017-11-05) initial version
- optimized for Taulman PCTPE

V1.1 (2017-11-05)
- increased air gap to 2 layers
- number of air gap layers now configurable
- fixed top width not scaling with case wall thickness
- increased cutout Z for left and right cutouts

V1.2 (2017-11-12)
- now optimized for Semiflex (Cheetah)
-- layerHeight 0.1->0.15 and other changes related to using softer material
- slightly increased bottom cutout Z
- top width and hight will now scale only 75% with wall thickness (was 100%)
- increased bottom thickness, so camera is better protected: 1.1 -> 1.8
- slightly decreased hingeXAdditional: 2.0 -> 1.75
- slightly decreased width of credit card pockets
- increased extraYOffsetPerPocket 1.5->2.5
- fixed airgapLayers not working for credit card pockets

V1.3 (2017-11-26)
- Fixed hinge Z was negative, so first layer was hinge only
- some changes to underside thickness and cutouts no longer go all the way down to z=0

V1.4 (2017-12-12)
- added engraved text
- Finetuning
-- standLayer 9 -> 7
-- decreased wall thicknesses for case by 0.3mm
-- reduced topZLayers and extraTopPocketLayer by 1
-- phoneDimensionAdditional X/Y/Z 0.00 -> -0.25
-- case_top_cutoff 0.45 -> 0.48;
*/

/*
Optmized for Semiflex (Cheetah)
For taulman PCTPE change following:
layerHeight: 0.1
standLayer: 5
caseSideThickness: 1.9
caseTopBottomThickness: 1.9
phoneDimensionAdditionalX: 0.1
phoneDimensionAdditionalY: 0.1
phoneDimensionAdditionalZ: 0.1
*/

/* [Main] */
layerHeight=0.15;
caseSideThickness=2.1;
caseTopBottomThickness=2.1;
caseUndersideThickness=2.1;
// position of the stand layer; -1=none
standLayer=7; // [-1:1:20]
// position of the extra pocket layer; 0=none
extraTopPocketLayer=6; // [0:1:20]
// number of credit card pockets; 0=none
numberCreditCardPockets=3; // [0:1:4]
// height of top without credit card pockets; 0=no top, i.e. bumper case
topZLayers=10; // [0:1:20]
// credit card pocket top thickness
creditCardPocketTopLayers=3; // [1:1:5]
// number of layers for air gap
airGapLayers=2; // [1:1:3]
// hinge thickness; 0=none
hingeZLayers=2; // [0:1:20]
// extra space for credit cards and money between phone and top
hingeAdditional=1.75;
// make additional space for phone, use i.e. to offset print precision issues. For very flexible materials you may want to use negative values
phoneDimensionAdditionalX=-0.25;
phoneDimensionAdditionalY=-0.25;
phoneDimensionAdditionalZ=-0.25;

// engraved text
engravedText="OnePlus";
engravedTextLayers=2;
engravedTextSize=8;
engravedTextSpacing=1.2;
engravedTextPosX=-68;
engravedTextPosY=-70;
engravedTextFont="Liberation Sans";

/* [Hidden] */
$fn=50;
phone=[75.2+phoneDimensionAdditionalX,153.0+phoneDimensionAdditionalY,7.8+phoneDimensionAdditionalZ]; // phone dimesions x,y,z

// --- cutouts ---
// volume and alert slider
volumeslider=[45-3,24,30];
posCutout1=[-36.5,-2,-1];
// power button
powerbutton=[15-3,24,30];
posCutout2=[23.5,-2,-1];
// bottom (usb+headphone+speaker)
bottomCutout=[40-3,28,30];
posCutout3=[0,-2,-1.2];
// camera
camera_loc=[0,57];
camera=[18,29,20];
camera_rounding=3;

// --- cutoffs ---
case_top_cutoff=0.48;
case_bottom_cutoff=1.7;

// --- phone and case spefific rounding ---
phone_edge=11;
phone_edge_r=37;
rounding=1.7;
s_scale=[3.5,3.5,1];
case_rounding=4;
case_rounding_sphere=2;

// case size offset x,y,z
caseWall=[caseSideThickness,
caseTopBottomThickness, caseUndersideThickness+case_bottom_cutoff];

hingeX=phone[2]+caseWall[0]+caseWall[2]+hingeAdditional;
hingeWidth=hingeX+hingeAdditional;
hingeZ=hingeZLayers*layerHeight;

topZ=topZLayers*layerHeight;

OVERLAP=0.005;

function creditCardZ()=airGapLayers*layerHeight;

creditCardSpace=[65.4,75]; // x in mm, y in mm
bottomThickness=0;
creditCardPocketSeam=1;
seamTopPocket=1.5;
creditCardPocketTop=layerHeight*creditCardPocketTopLayers;
zOffset=0+creditCardZ()+creditCardPocketTop;
creditCardPocketsStartOffset=2;
creditCardPocketYOffsetPerPocket=19;
creditCardPocketHeight=bottomThickness+creditCardZ()+creditCardPocketTop;
extraYOffsetPerPocket=2.5;

difference(){
    bumper();
    standCutout();
}

if (topZLayers > 0){
    hinge();
    difference(){
        top();
        extraTopPocket();
        translate([0,0,-OVERLAP])
        engravedText();
    }

    if (numberCreditCardPockets > 0){
        translate([0,creditCardPocketsStartOffset,0])
        creditCardPockets();
    }
}

module bumper(){
    translate([0,0,-case_bottom_cutoff])
    difference(){
        difference(){
            resize(newsize=[phone[0]+2*caseWall[0],phone[1]+2*caseWall[1],phone[2]+caseWall[2]])
            phone();

            translate([0,0,phone[2]+caseWall[2]+10/2-case_top_cutoff])
            cube([phone[0]*2,phone[1]*2,10], center=true);

            translate([0,0,-10/2+case_bottom_cutoff])
            cube([phone[0]*2,phone[1]*2,10], center=true);
        }
        translate([0,0,caseWall[2]])
        union(){
            phone();
            phone_cutouts();
        }
    }
}

module standCutout(){
    sizeFactor=2;
    color([1,0,0])
    translate([-phone[0]/2*sizeFactor,-phone[1]/2*sizeFactor,(standLayer-1)*layerHeight])
    cube([sizeFactor*phone[0]/2,sizeFactor*phone[1],airGapLayers*layerHeight]);
}

module extraTopPocket(){
    zOffset=(airGapLayers*layerHeight)/topZ;
    color([1,0,0])
    scale([1,(phone[1]-2*seamTopPocket)/phone[1],1])
    translate([seamTopPocket,0,(extraTopPocketLayer-1)*layerHeight])
    scale([1,(phone[1]-2*seamTopPocket)/phone[1],zOffset])
    top();
}

module top(){
    scaleSizeWithWallThicknessFactor=0.75;
    translate([-1.5*phone[0]-hingeX+case_rounding-scaleSizeWithWallThicknessFactor*caseWall[0],-phone[1]/2+1.5*case_rounding-scaleSizeWithWallThicknessFactor*caseWall[1],0])
    difference(){
        minkowski(){
            cube([phone[0]-2*1.5*case_rounding-case_rounding_sphere+2*scaleSizeWithWallThicknessFactor*caseWall[0],phone[1]-2*1.5*case_rounding+2*scaleSizeWithWallThicknessFactor*caseWall[1],topZ]);
            cylinder(r=case_rounding*1.5,h=case_rounding);
        }
        translate([-case_rounding*1.5-OVERLAP/2,-case_rounding*1.5-OVERLAP/2,topZ])
        cube([phone[0]+OVERLAP+case_rounding_sphere+caseWall[0],phone[1]+OVERLAP+2*caseWall[1],100]);
    }
}

module creditCardPockets(){
      translate([-phone[0]-hingeWidth-caseWall[0]/2,-phone[1]/2+creditCardSpace[0]/2+creditCardPocketSeam+case_rounding,topZ])
      {
      for (i=[1:numberCreditCardPockets]){
        creditCardPocket(i,numberCreditCardPockets);
      }
      }
}

module creditCardPocket(pocketNumber,totalNumber){
    yOffset=(totalNumber-pocketNumber)*creditCardPocketYOffsetPerPocket;
    extraYOffset=(totalNumber-pocketNumber)*extraYOffsetPerPocket;
    zOffset=(pocketNumber-1)*creditCardPocketHeight+creditCardPocketHeight/2;

    translate([0,yOffset/2+totalNumber/2*extraYOffsetPerPocket-extraYOffset/2,zOffset]){
        cube([creditCardSpace[0]+extraYOffset,creditCardSpace[1]+yOffset,bottomThickness], center=true);

        difference(){
            cube([creditCardSpace[0]+extraYOffset,creditCardSpace[1]+yOffset,creditCardPocketHeight], center=true);

        translate([0,creditCardPocketSeam+yOffset/2,bottomThickness-(creditCardPocketHeight-creditCardZ())/2])
            cube([creditCardSpace[0]-2*creditCardPocketSeam,creditCardSpace[1]-creditCardPocketSeam,creditCardZ()+OVERLAP], center=true);
        }
    }
}

module hinge(){
    color([1,1,0])
    translate([-phone[0]/2-hingeWidth/2,0,hingeZ/2])
    cube([hingeX+hingeAdditional+2*case_rounding+caseWall[0],phone[1]+2*caseWall[1]-case_rounding,hingeZ], center=true);
}

module phone(){
    translate([-phone[0]/2,phone[1]/2,0])
    rotate([0,0,-90])
	difference()
	{
		intersection()
		{
			translate(
				[rounding*(s_scale[0]),
				rounding*(s_scale[1]),
				0])
			minkowski()
			{
				cube([phone[1]-2*rounding*s_scale[0],
					phone[0]-2*rounding*s_scale[1],
					phone[2]-rounding*s_scale[2]]);

				scale(s_scale)
				difference()
				{
					sphere(rounding);
					translate([-rounding,-rounding,-2*rounding])
					cube(2*rounding);
				}
			}

			translate([0,phone[0]/2,phone[2]/2])
				scale([1,1,0.3])
					rotate(90,[0,1,0])
						cylinder(phone[1],d=phone[0], $fn=$fn*3);

			translate([phone[1]/2,0,phone[2]/2])
				scale([1,1,0.25])
					rotate(-90,[1,0,0])
						cylinder(phone[0],d=phone[1], $fn=$fn*3);

		}
		// bottom edge roundings
		for (i = [-1:2:1])
		{
			translate([-1,
				phone_edge*-i+phone[0]*(i/2+0.5),
				phone_edge_r-0.001])
				rotate(90,[0,1,0])
					rotate(-45+i*45,[0,0,1])
						difference()
						{
				cube([phone_edge_r, phone_edge_r, phone[1]+2]);
				cylinder(phone[1]+2,r=phone_edge_r, $fn=$fn*3);
						}
		}
	}
}

module phone_cutouts(){
	// camera
	translate([camera_loc[0], camera_loc[1], -camera_loc[2]+camera_rounding])
	minkowski()
	{
		cube([camera[0]-2*camera_rounding,
			camera[1]-2*camera_rounding,
			camera[2]], center=true);
		difference()
		{
			sphere(r=camera_rounding);
			translate([-camera_rounding,-camera_rounding,0])
				cube(2*camera_rounding);
		}
	}

        phone_cutout_helper("LEFT",posCutout1,volumeslider);

        phone_cutout_helper("RIGHT",posCutout2,powerbutton);

        phone_cutout_helper("BOTTOM",posCutout3,bottomCutout);
}

// phoneSideAlias=LEFT/RIGHT/TOP/BOTTOM/UPPER/UNDER
// posVector=[x,y,z]
// sizeVector=[width,height,depth]
module phone_cutout_helper(phoneSideAlias,posVector,sizeVector){
    dZ=sizeVector[1]/2; // default Z offset
    if (phoneSideAlias=="LEFT"){
        offsetVector=[-phone[0]/2-posVector[1],-posVector[0],dZ+posVector[2]];
        rotateVector=[-90,0,90];
        phone_cutout(sizeVector,offsetVector,rotateVector);
    } else if (phoneSideAlias=="RIGHT"){
        offsetVector=[phone[0]/2+posVector[1],posVector[0],dZ+posVector[2]];
        rotateVector=[90,0,90];
        phone_cutout(sizeVector,offsetVector,rotateVector);
    } else if (phoneSideAlias=="TOP"){
        // TODO
    } else if (phoneSideAlias=="BOTTOM"){
        offsetVector=[posVector[0],-phone[1]/2-posVector[1],dZ+posVector[2]];
        rotateVector=[90,0,0];
        phone_cutout(sizeVector,offsetVector,rotateVector);
    } else if (phoneSideAlias=="UPPER"){
        // TODO
    } else if (phoneSideAlias=="UNDER"){
        offsetVector=[posVector[0],phone[1]/2+posVector[1],dZ+posVector[2]];
        rotateVector=[0,180,90];
        phone_cutout(sizeVector,offsetVector,rotateVector);
    }
}

// sizeVector=[width,height,depth]
module phone_cutout(sizeVector,offsetVector,rotateVector){
    color([1,0,0])
    translate([offsetVector[0],offsetVector[1],offsetVector[2]])
    rotate([rotateVector[0],rotateVector[1],rotateVector[2]])
    translate([-sizeVector[0]/2+sizeVector[1]/6,0,0])
			hull()
			{
					cylinder(d=sizeVector[1],h=sizeVector[2]);
				translate([sizeVector[0]-sizeVector[1]/3,0,0])
					cylinder(d=sizeVector[1],h=sizeVector[2]);
			}
}

module engravedText(){
    color([1,0,0])
    translate ([engravedTextPosX,engravedTextPosY,engravedTextLayers*layerHeight])
    rotate ([0,180,0])
    linear_extrude(engravedTextLayers*layerHeight)
        text(engravedText, font = engravedTextFont, size = engravedTextSize, spacing = engravedTextSpacing );
}
```


[User]
I'm looking to create a customizable 2D paper airplane design that I can 3D print. I want to be able to control the overall size, the thickness of the outlines, and the height of the final printed piece. It seems like the design should be based on a series of points and polygons, and I'd like an option to flip the design horizontally.

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

*   `max_size_in_millimeter`: This should control the size of the longest side of the airplane. The shorter side should be scaled proportionally to keep the aspect ratio. Let's say I'd like to be able to specify a size between 20mm and 300mm.
*   `model_height_in_millimeter`: The height (thickness) of the final extrusion. I should be able to set this from 0.2mm to 100mm in 0.2mm increments.
*   `outline_size_in_millimeter`: The thickness of the outer outline of the paper airplane. I'd want to be able to set this between 0.5 and 20mm, in increments of 0.1mm.
*  `inline_size_in_millimeter`: The thickness of the inner outlines. I also want this between 0.5mm and 20mm, in 0.1mm increments.
* `inline_edge_radius_in_millimeter`: The radius of the rounded ends of the inner outlines, adjustable between 0 and 5mm in 0.1mm increments.
*   `flip_model`: A simple yes/no option to flip the model horizontally.

The basic shape of the airplane should be based on these points:

**Outer Points:**

*   A1 = \[64, 133]
*   A2 = \[1997, 513]
*   A3 = \[1588, 698]
*   A4 = \[1468, 1103]
*   A5 = \[1153, 888]
*   A6 = \[882, 1002]

These points create the `outline`.

**Inner Point:**

*   B1 = \[1420, 772]

And these point sets should define the `cut_polygons`:

*   C1 = \[A1, A6, A5, B1]
*   C2 = \[A5, B1, A4]
*   C3 = \[A4, A3, A1, B1]
*   C4 = \[A3, A2, A1]

I believe it needs to calculate the scaling factors based on the initial dimensions and the `max_size_in_millimeter` parameter, and then resize the model.

Could you generate an OpenSCAD file for me with this setup? I don't need any extra libraries for this.

[Assistant]
customizable_origami_paperplane.scad:
```
/*
 * Customizable Origami - Paperplane - https://www.thingiverse.com/thing:2627080
 * by Dennis Hofmann - https://www.thingiverse.com/mightynozzle/about
 * created 2017-11-05
 * 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.1; //[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 = [64, 133];
A2 = [1997, 513];
A3 = [1588, 698];
A4 = [1468, 1103];
A5 = [1153, 888];
A6 = [882, 1002];

outline = [A1, A2, A3, A4, A5, A6];

// Inner Points
B1 = [1420, 772];

// Polygons
C1 = [A1, A6, A5, B1];
C2 = [A5, B1, A4];
C3 = [A4, A3, A1, B1];
C4 = [A3, A2, A1];

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

min_x = A1[0];
min_y = A1[1];
max_x = A2[0];
max_y = A4[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);
                    }
                }
            }
        }
    }
}

```