[User]
I'd like to create a customizable 2D origami eagle design in OpenSCAD. The design is based on a series of points and polygons, and I want to be able to adjust things like the overall size, height, and the thickness of the lines that make up the eagle.

Here's what I need:

*   **Overall Size:** I need to be able to specify the maximum size of the longest side of the eagle. The other side should automatically scale proportionally.
*   **Height:** I need to be able to set the height/thickness of the 2D shape (how thick it is when extruded).
*   **Outline Thickness:** I need to be able to set the thickness of the outer border of the eagle.
*   **Inner Line Thickness:** I need to be able to control the thickness of the lines that make up the internal structure of the eagle.
*   **Inner Line End Roundness:** I want to be able to add a radius to the ends of the inner lines to make them rounded.
*   **Flip Option:** I need a setting to flip the model horizontally.

The eagle's shape is defined by the following points (and I will provide the full list of point coordinates):

```
// Outer Points
A1 = [155, 55];
A2 = [693, 234];
A3 = [763, 274];
A4 = [832, 286];
A5 = [870, 336];
A6 = [919, 366];
A7 = [954, 407];
A8 = [1017, 291];
A9 = [1136, 288];
A10 = [1147, 269];
A11 = [1264, 251];
A12 = [1340, 189];
A13 = [1369, 193];
A14 = [1525, 191];
A15 = [1566, 153];
A16 = [1582, 155];
A17 = [1602, 133];
A18 = [1654, 114];
A19 = [1673, 92];
A20 = [1696, 102];
A21 = [1602, 184];
A22 = [1582, 220];
A23 = [1553, 234];
A24 = [1507, 317];
A25 = [1334, 776];
A26 = [1328, 851];
A27 = [1371, 861];
A28 = [1415, 884];
A29 = [1526, 981];
A30 = [1545, 1029];
A31 = [1539, 1037];
A32 = [1563, 1092];
A33 = [1571, 1157];
A34 = [1555, 1146];
A35 = [1539, 1111];
A36 = [1480, 1067];
A37 = [1492, 1056];
A38 = [1402, 1025];
A39 = [1227, 1056];
A40 = [1161, 1005];
A41 = [1122, 1006];
A42 = [1152, 1093];
A43 = [1156, 1121];
A44 = [1141, 1157];
A45 = [1208, 1262];
A46 = [1210, 1275];
A47 = [1244, 1289];
A48 = [1253, 1306];
A49 = [1287, 1344];
A50 = [1280, 1348];
A51 = [1258, 1324];
A52 = [1222, 1317];
A53 = [1198, 1285];
A54 = [1182, 1312];
A55 = [1042, 1172];
A56 = [1028, 1127];
A57 = [1014, 1112];
A58 = [1010, 1072];
A59 = [998, 1127];
A60 = [982, 1155];
A61 = [965, 1170];
A62 = [1029, 1295];
A63 = [1029, 1314];
A64 = [1056, 1318];
A65 = [1095, 1384];
A66 = [1074, 1379];
A67 = [1055, 1355];
A68 = [1030, 1343];
A69 = [989, 1335];
A70 = [918, 1247];
A71 = [872, 1232];
A72 = [849, 1182];
A73 = [832, 1129];
A74 = [825, 1059];
A75 = [832, 985];
A76 = [844, 949];
A77 = [779, 933];
A78 = [672, 968];
A79 = [578, 956];
A80 = [573, 939];
A81 = [745, 842];
A82 = [814, 793];
A83 = [801, 608];
A84 = [721, 538];
A85 = [647, 486];
A86 = [537, 511];
A87 = [469, 512];
A88 = [412, 363];
A89 = [350, 378];
A90 = [285, 209];

```

And these are the inner points:

```
// Inner Points
B1 = [783, 882];
B2 = [849, 928];
B3 = [881, 842];
B4 = [1005, 912];
B5 = [1014, 1002];
B6 = [1048, 1005];
B7 = [1038, 1042];
B8 = [1016, 1038];
B9 = [907, 1221];
B10 = [1125, 1141];
B11 = [1358, 1007];
B12 = [1255, 831];
B13 = [1258, 805];
B14 = [1070, 560];
B15 = [1308, 250];
B16 = [1219, 280];
B17 = [1095, 746];
B18 = [985, 696];
B19 = [1084, 1209];
```

The eagle is defined by these polygons, each one using the above defined points. I need to define these as lists of points:

```
// Polygons
C1 = [A1, A2, A90];
C2 = [A90, A2, A3, A88, A89];
C3 = [A3, A4, A87, A88];
C4 = [A87, A4, A5, A85, A86];
C5 = [A85, A5, A6, A7, B14, B13, B12, B17, B18, A83, A84];
C6 = [A9, B16, A23, A22, B15, A11, A10];
C7 = [A11, A12, A13, A14, A21, A22, B15];
C8 = [A14, A21, A16, A15];
C9 = [A16, A17, A18, A19, A20, A21];
C10 = [A7, A24, A23, B16, A9, A8];
C11 = [A7, A24, A25, A26, B12, B13, B14];
C12 = [B12, A39, A38, B11, A28, A27, A26];
C13 = [A28, B11, A38, A37, A29];
C14 = [A36, A37, A29, A30, A31, A32, A33, A34, A35];
C15 = [B12, A39, B17];
C16 = [A39, B17, B18, B4, A40];
C17 = [B4, B5, B6, A41, A40];
C18 = [B8, B7, B6, B5];
C19 = [A41, A42, A43, B10, B19, A55, A56, A57, A58, B8, B7, B6];
C20 = [A43, A44, A45, A53, A54, B19, B10];
C21 = [A53, A45, A46, A47, A48, A49, A50, A51, A52];
C22 = [A71, B9, A61, A62, A63, A69, A70];
C23 = [A63, A64, A65, A66, A67, A68, A69];
C24 = [A79, B1, B2, A76, A77, A78];
C25 = [A80, A79, B1, A81];
C26 = [A82, B3, B2, B1, A81];
C27 = [A82, A83, B18, B4, B2, B3];
C28 = [B4, B5, B8, A58, A59, A60, A61, B9, A71, A72, A73, A74, A75, A76, B2];

```

The outer edge of the eagle is all the points of type A. I'd like to extrude the shape, creating the eagle design with the parameters mentioned before. I want to use the polygon function in openscad to create the overall shape, and then use offset operations to create the outline and inner details. Could you help me generate this OpenSCAD file? I don't need any external libraries for this, just the standard OpenSCAD functionality.

[Assistant]
customizable_origami_eagle.scad:
```
/*
 * Customizable Origami - Eagle - https://www.thingiverse.com/thing:2775144
 * by Dennis Hofmann - https://www.thingiverse.com/mightynozzle/about
 * created 2018-01-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.6; //[0.0:0.1:5]

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

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

// Outer Points
A1 = [155, 55];
A2 = [693, 234];
A3 = [763, 274];
A4 = [832, 286];
A5 = [870, 336];
A6 = [919, 366];
A7 = [954, 407];
A8 = [1017, 291];
A9 = [1136, 288];
A10 = [1147, 269];
A11 = [1264, 251];
A12 = [1340, 189];
A13 = [1369, 193];
A14 = [1525, 191];
A15 = [1566, 153];
A16 = [1582, 155];
A17 = [1602, 133];
A18 = [1654, 114];
A19 = [1673, 92];
A20 = [1696, 102];
A21 = [1602, 184];
A22 = [1582, 220];
A23 = [1553, 234];
A24 = [1507, 317];
A25 = [1334, 776];
A26 = [1328, 851];
A27 = [1371, 861];
A28 = [1415, 884];
A29 = [1526, 981];
A30 = [1545, 1029];
A31 = [1539, 1037];
A32 = [1563, 1092];
A33 = [1571, 1157];
A34 = [1555, 1146];
A35 = [1539, 1111];
A36 = [1480, 1067];
A37 = [1492, 1056];
A38 = [1402, 1025];
A39 = [1227, 1056];
A40 = [1161, 1005];
A41 = [1122, 1006];
A42 = [1152, 1093];
A43 = [1156, 1121];
A44 = [1141, 1157];
A45 = [1208, 1262];
A46 = [1210, 1275];
A47 = [1244, 1289];
A48 = [1253, 1306];
A49 = [1287, 1344];
A50 = [1280, 1348];
A51 = [1258, 1324];
A52 = [1222, 1317];
A53 = [1198, 1285];
A54 = [1182, 1312];
A55 = [1042, 1172];
A56 = [1028, 1127];
A57 = [1014, 1112];
A58 = [1010, 1072];
A59 = [998, 1127];
A60 = [982, 1155];
A61 = [965, 1170];
A62 = [1029, 1295];
A63 = [1029, 1314];
A64 = [1056, 1318];
A65 = [1095, 1384];
A66 = [1074, 1379];
A67 = [1055, 1355];
A68 = [1030, 1343];
A69 = [989, 1335];
A70 = [918, 1247];
A71 = [872, 1232];
A72 = [849, 1182];
A73 = [832, 1129];
A74 = [825, 1059];
A75 = [832, 985];
A76 = [844, 949];
A77 = [779, 933];
A78 = [672, 968];
A79 = [578, 956];
A80 = [573, 939];
A81 = [745, 842];
A82 = [814, 793];
A83 = [801, 608];
A84 = [721, 538];
A85 = [647, 486];
A86 = [537, 511];
A87 = [469, 512];
A88 = [412, 363];
A89 = [350, 378];
A90 = [285, 209];

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, A39, A40, A41, A42, A43, A44, A45, A46, A47, A48, A49, A50, A51, A52, A53, A54, A55, A56, A57, A58, A59, A60, A61, A62, A63, A64, A65, A66, A67, A68, A69, A70, A71, A72, A73, A74, A75, A76, A77, A78, A79, A80, A81, A82, A83, A84, A85, A86, A87, A88, A89, A90];

// Inner Points
B1 = [783, 882];
B2 = [849, 928];
B3 = [881, 842];
B4 = [1005, 912];
B5 = [1014, 1002];
B6 = [1048, 1005];
B7 = [1038, 1042];
B8 = [1016, 1038];
B9 = [907, 1221];
B10 = [1125, 1141];
B11 = [1358, 1007];
B12 = [1255, 831];
B13 = [1258, 805];
B14 = [1070, 560];
B15 = [1308, 250];
B16 = [1219, 280];
B17 = [1095, 746];
B18 = [985, 696];
B19 = [1084, 1209];

// Polygons
C1 = [A1, A2, A90];
C2 = [A90, A2, A3, A88, A89];
C3 = [A3, A4, A87, A88];
C4 = [A87, A4, A5, A85, A86];
C5 = [A85, A5, A6, A7, B14, B13, B12, B17, B18, A83, A84];
C6 = [A9, B16, A23, A22, B15, A11, A10];
C7 = [A11, A12, A13, A14, A21, A22, B15];
C8 = [A14, A21, A16, A15];
C9 = [A16, A17, A18, A19, A20, A21];
C10 = [A7, A24, A23, B16, A9, A8];
C11 = [A7, A24, A25, A26, B12, B13, B14];
C12 = [B12, A39, A38, B11, A28, A27, A26];
C13 = [A28, B11, A38, A37, A29];
C14 = [A36, A37, A29, A30, A31, A32, A33, A34, A35];
C15 = [B12, A39, B17];
C16 = [A39, B17, B18, B4, A40];
C17 = [B4, B5, B6, A41, A40];
C18 = [B8, B7, B6, B5];
C19 = [A41, A42, A43, B10, B19, A55, A56, A57, A58, B8, B7, B6];
C20 = [A43, A44, A45, A53, A54, B19, B10];
C21 = [A53, A45, A46, A47, A48, A49, A50, A51, A52];
C22 = [A71, B9, A61, A62, A63, A69, A70];
C23 = [A63, A64, A65, A66, A67, A68, A69];
C24 = [A79, B1, B2, A76, A77, A78];
C25 = [A80, A79, B1, A81];
C26 = [A82, B3, B2, B1, A81];
C27 = [A82, A83, B18, B4, B2, B3];
C28 = [B4, B5, B8, A58, A59, A60, A61, B9, A71, A72, A73, A74, A75, A76, 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, C28];

min_x = A1[0];
min_y = A1[1];
max_x = A20[0];
max_y = A65[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 design some custom wheels for my Traxxas Rustler RC car, and I need a little help with the OpenSCAD code. I have a general idea of what I want, based on a design I found, but I'd like to make it more flexible for different uses and perhaps make the code more modular.

Basically, I need a wheel with paddles for snow or sand, but I'd like to control all the dimensions parametrically. The existing code had quite a few parameters, which I'll list here, along with some clarifications and some ideas I have for extending it. I want to make sure the design can easily be adjusted for different wheel sizes and paddle configurations.

Here's the basic rundown of what I need to be able to adjust:

*   **Core Wheel Dimensions:**
    *   `coreWheelDia`: The overall diameter of the wheel, excluding the paddles.
    *   `coreWheelWidth`: The width of the main part of the wheel.
    *   `tireEdgeRoundOffRadius`: How much the outer edges of the wheel are rounded.

*   **Hub/Mounting:**
    *   `hubClearanceInnerDia`: The diameter of the recessed opening on the inside of the wheel for clearance.
    *   `hubClearanceDepth`: The depth of that recessed opening.
    *   `hexInsertDia`: The diameter of the hex-shaped recess for the wheel adapter.
    *   `hexInsertDepth`: The depth of the hex recess.
    *   `spindleShaftDia`: The diameter of the axle shaft hole.
    *   `spindleShaftHoleThickness`: The thickness of the material around the axle shaft hole.
    *   `nutFlatDia`: The diameter of the flat surface around the axle hole, where the nut tightens down.

*   **Paddles:**
    *   `numberOfPaddles`: How many paddles around the wheel.
    *   `paddleInset`: How far the paddles are set in from the edge of the wheel.
    *   `paddleLength`: How tall the paddles stick out from the wheel surface.
    *   `paddleThickness`: How thick the paddle blades are.
    *   `paddleAngle`: The tilt angle of the paddles (forward or backward).
	*	`paddleOverlap` How far into the wheel the base of the paddle sticks to help with the connection

*   **Spokes:**
    *   `numberOfSpokes`: How many spoke openings (or spokes) are present.
    *   `spokeCornerRoundnessDia`: The radius to round off the corners of the spoke openings.
    *   `spokeHubDia`: The diameter of the central solid area of the wheel around the axle.
	*  `spokeSlotInset`: How far into the solid wheel the edges of the spoke openings are inset.

**Improvements/Additional Features:**

1.  **Separate Front/Rear Wheels:** I'd like the design to be set up to handle both front and rear wheels, even though the only difference is the hex/hub setup. Maybe one file that includes parameters for front or back and then renders the correct wheel? The front wheels for a 2WD Traxxas Rustler don't need a hex insert, they use a bearing, so that would be a good starting point for the front wheel parameters. Perhaps just use the same core wheel design, and then just have it not include the hex for the front and instead include a bearing hole.
2.  **Bearing Option:** For the front wheels, I'd like to have a parameter for specifying a standard bearing size, and to have the code create an appropriately sized hole to accommodate it. (Likely this means a diameter parameter, and an appropriate bearing depth.)
3.  **Tire Bead:** It would be nice to be able to easily add a "tire bead" to the outer edge of the wheel. It could be controlled by a simple size and depth (e.g. `tireBeadDepth` and `tireBeadSize`). It would be an inset circular groove that could be added on the outer edge of the wheel and would improve ability for the wheel to hold onto a tire, should the user choose to use it that way.
4.  **Parameter Validation:** It would be helpful to have some simple parameter validation to prevent obviously incorrect wheel designs (e.g., `hubClearanceInnerDia` should always be smaller than `coreWheelDia`).
5.  **Modularity:** It would be great if the code was modular, so each part (core, hub, paddle, spokes) could be more easily modified or re-used. Functions that return a basic shape for each component might be a good idea.
6.  **Optional Paddles:** A parameter to turn paddles on or off completely for a basic wheel would be nice to allow the user to use it without paddles, if desired.
7.  **Paddle Profile:** A parameter for the paddle profile, currently a rectangle, but allowing other profiles like a trapezoid or triangle would add a lot of functionality and potential to use the model for other applications.
8.  **Improved Paddle Connection:** If possible, calculate a better `paddleOverlap` based on other parameters, rather than having the user define it.

I'm hoping you can help me put together the OpenSCAD files. I'm happy to start with a basic wheel design and then build on that. I don't need anything too fancy to start, just make sure the parametric functionality is there, especially since I'll probably be iterating on the design and experimenting with different parameter values. I think you can get a lot of the basic geometry from the existing code, but it would be nice to clean it up and add some validation and more modularity.

I think this can all be done without the use of external libraries. Thanks!

[Assistant]
traxxas_snow_wheel_rear.scad:
```
// Ice Wheel for 1/10 Traxxas Rustler (maybe others) - Rear

// CUSTOMIZER VARIABLES

// Diameter of the wheel without the claws:
coreWheelDia=110; // [80:150]

// Width of the wheel (needs to be larger than hubClearanceDepth + hexInsertDepth + spindleShaftHoleThickness):
coreWheelWidth=50; // [30:100]

// How much the edge of the wheel is "rounded off"
tireEdgeRoundOffRadius=5; // [1:10]

// The size of the opening on the inside / back-side of the wheel (needs to be smaller than coreWheelDia):
hubClearanceInnerDia=80; // [60:140]

// The depth of the opening on the inside/back-side of the wheel:
hubClearanceDepth=25; // [15:35]

// Measurement from point to point of the hex insertion recess:
hexInsertDia=14.5; // [10:20]

// Depth of the hex insertion recess:
hexInsertDepth=4; // [3:6]

// Diameter of the axle-shaft hole:
spindleShaftDia=5; // [3:8]

// Thickness of the wheel around the axle-shaft hole:
spindleShaftHoleThickness=4; // [3:6]

// Diameter of the flat area (where the axle-nut tightens down):
nutFlatDia=12; // [10:20]

// How many paddles:
numberOfPaddles=8; // [8:20]

// How far in the paddles are from the edge of the wheel:
paddleInset=6; // [0:15]

// How tall the paddle is up from the wheel surface:
paddleLength=15; // [1:25]

// How thick the "blade" of the paddle is:
paddleThickness=3; // [2:6]

// How far over each paddle tilts (degrees):
paddleAngle=-20; // [-60:60]

// How many spokes (or spoke slots... same thing):
numberOfSpokes=5; // [4,5,6]

// How much the corners of the spoke-slots are "rounded off":
spokeCornerRoundnessDia=5; // [1:10]

// How much solid space to reserve in the center of the wheel:
spokeHubDia=30; // [20:80]

// How much solid space to reserve outside the spoke-slots:
spokeSlotInset=3; // [0:20]

// How far into the wheel the base of the paddle sticks (compensates, if necessary, for higher paddle tilt or thickness, or smaller-wheel curve, to make a solid, connected object):
paddleOverlap=3; // [2:6]

// TODO: Calculate paddle overlap instead of requiring it to be manually set.

//CUSTOMIZER VARIABLES END

overlap=0.01*1;

$fn=50*1;

outerConeDepth=coreWheelWidth
        -hubClearanceDepth
        -hexInsertDepth
        -spindleShaftHoleThickness;

union() {
    difference() {
        translate([0,0,tireEdgeRoundOffRadius]) {
            minkowski() {
                cylinder(d=coreWheelDia-tireEdgeRoundOffRadius*2,
                    h=coreWheelWidth-tireEdgeRoundOffRadius*2);
                sphere(r=tireEdgeRoundOffRadius);
            }
        }
        translate([0,0,coreWheelWidth-hubClearanceDepth])
            cylinder(d=hubClearanceInnerDia,
                h=hubClearanceDepth+overlap);
        translate([0,0,
                coreWheelWidth-hubClearanceDepth-hexInsertDepth])
            cylinder(d=hexInsertDia,
                h=hexInsertDepth+overlap, $fn=6);
        translate([0,0,-overlap])
            cylinder(d=spindleShaftDia, h=coreWheelWidth+overlap*2);
        translate([0,0,-overlap])
            cylinder(d1=hubClearanceInnerDia, d2=nutFlatDia,
            h=outerConeDepth+overlap);
        spokeCutouts();
    }
    // Paddles
    paddleSeparationAngle=360/numberOfPaddles;
    for (s=[1:numberOfPaddles]) {
        rotate([0,0,paddleSeparationAngle*s])
        translate([coreWheelDia/2-overlap-paddleOverlap, 0, paddleInset])
            rotate([0,0,paddleAngle])
                cube([paddleLength+paddleOverlap,
                    paddleThickness,coreWheelWidth-paddleInset*2]);
    }

}

module spokeCutouts() {
    // Spokes
    // Note: Spoke material is same size as spoke opening
    spokeHalfAngle=360/numberOfSpokes/4;
    for (s=[0:numberOfSpokes-1]) {
        rotate([0,0,s*(spokeHalfAngle*4)])
        hull() {
            // inner
            rotate([0,0,-spokeHalfAngle])
                translate([(spokeHubDia+spokeCornerRoundnessDia)/2
                        ,0,0])
                    cylinder(d=spokeCornerRoundnessDia,
                        h=coreWheelWidth);
            rotate([0,0,spokeHalfAngle])
                translate([(spokeHubDia+spokeCornerRoundnessDia)/2
                        ,0,0])
                    cylinder(d=spokeCornerRoundnessDia,
                        h=coreWheelWidth);
            // outer
            rotate([0,0,-spokeHalfAngle])
                translate([(hubClearanceInnerDia-
                        spokeCornerRoundnessDia)/2-spokeSlotInset,
                                0,0])
                    cylinder(d=spokeCornerRoundnessDia,
                        h=coreWheelWidth);
            rotate([0,0,spokeHalfAngle])
                translate([(hubClearanceInnerDia
                        -spokeCornerRoundnessDia)/2-spokeSlotInset,
                            0,0])
                    cylinder(d=spokeCornerRoundnessDia,
                        h=coreWheelWidth);
        }
    }
}
```


[User]
I'd like a parametric OpenSCAD design based on the "Customizable Geometry - Two Boxes" design, but with a few tweaks and some more flexibility.

The basic idea is still two connected boxes/outlines, but instead of having pre-defined coordinates for the outline and inner shapes, I'd like to define a list of `outer_points` and a list of `inner_points`. The code should then generate polygons from these, connecting the points in order. I need to be able to specify both the outer polygon and then multiple inner polygons separately. The inner polygons should all be treated as cutouts from the outer shape.

The parameters should be the following:

*   `max_size`: The maximum dimension of the design, which should scale the whole thing proportionally.
*   `model_height`: The extrusion height of the design.
*   `outline_size`: The thickness of the outer outline.
*   `inline_size`: The thickness of the inner outlines.
*   `inline_edge_radius`: The radius of the rounded edges of the inner outlines.
*   `flip_model`: A boolean parameter (true/false) to flip the model along the y-axis.
*   `outer_points`: A list of 2D points, defining the outer perimeter.
*   `inner_points`: A list of lists of 2D points, defining the inner cutouts/perimeters.

I'd also like the code to handle scaling appropriately so that no matter the shape of the initial outlines, they fit within the specified `max_size` parameter. It should calculate the bounding box of all the coordinates provided, and scale to fit.

The design should use `linear_extrude` with appropriate `offset` and `difference` operations. Make sure the `convexity` parameter is set appropriately when using the polygon function, and also make sure to use `$fn=32` when calculating the circles to use with `offset`. Also, don't forget to scale each parameter appropriately when scaling the design - for example `inline_size` will be dependent on `max_size`.

Can you create this?

[Assistant]
customizable_geometry_two_boxes.scad:
```
/*
 * Customizable Geometry - Two Boxes https://www.thingiverse.com/thing:2776180
 * by Dennis Hofmann - https://www.thingiverse.com/mightynozzle/about
 * created 2018-01-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.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 = [599, 580];
A2 = [598, 342];
A3 = [1293, 51];
A4 = [1755, 339];
A5 = [1758, 1058];
A6 = [1295, 1247];
A7 = [1296, 1483];
A8 = [601, 1762];
A9 = [142, 1483];
A10 = [141, 773];

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

// Inner Points
B1 = [600, 1056];
B2 = [825, 1194];
B3 = [822, 490];
B4 = [1064, 628];
B5 = [1293, 771];
B6 = [1062, 1335];
B7 = [1293, 533];
B8 = [824, 962];
B9 = [1069, 858];
B10 = [600, 1286];

// Polygons
C1 = [A1, A2, A3, A4, B7, B4, B3];
C2 = [B4, B7, B5, B9];
C3 = [B7, A4, A5, B5];
C4 = [B5, A5, A6, B6, B9];
C5 = [B3, B4, B9, B6, B2, B8];
C6 = [B8, B1, B10, B2];
C7 = [B8, B3, A1, A10, B1];
C8 = [A10, A9, B10, B1];
C9 = [B2, B6, A6, A7, A8, A9];

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

min_x = A10[0];
min_y = A3[1];
max_x = A5[0];
max_y = A8[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 want to create a customizable dice, but I'm not a programmer, so I'll need something really user-friendly. I've seen a design on Thingiverse (https://www.thingiverse.com/thing:2778633) that's almost exactly what I need - it's called Customizable Loaded Dice by SavageRodent. I'd like a parametric OpenSCAD design that lets me adjust the following:

*   **Dice Size:** I need to be able to specify the overall size of the dice (height, width, and depth).
*   **Wall Thickness:** It should be easy to control the thickness of the dice's walls.
*   **Load Size:** I want to create a loaded dice, so I need a parameter to control the volume of solid infill, which should cause the dice to land on one side more often. I need to be able to express this in a percentage of the internal volume, from 0% (no load) to 100% or even 200% for a solid infill.
*   **Loaded Number:** A setting that lets me specify which side of the dice should be weighted.
*   **Characters:** I need to choose between different symbol options for each face:
    *   **Text:** Allow me to set the text for each face. I also need to adjust things like font, bold, italic, spacing, size, direction, smoothness, alignment (both horizontal and vertical), and rotation.
    *   **Domed Dots:** Instead of text, I want the option for domed dots on each side. I need to adjust the dot size and spacing, and smoothness (number of polygons per dot)
    *   **Round Dots:** Also, I'd like a simple round dot option instead of the domed one. This should allow me to change dot size and spacing as well as smoothness (polygons per dot)
 *   **Dot Depth:** I need the depth of the embossed dots to be adjustable for the round dots (but not the domed ones).
*   **Dual Material Split:** An option to split the dice design into two parts: an outer shell and the inner core/characters. This is for printing with two materials. It would be ideal if setting this parameter generates two separate STL files.
*   **Preview Cutaway:** Finally, a preview parameter to cut away a quarter of the dice to see inside. This should be disabled before final rendering.

I'm not sure how the code should be structured, but it would be good to keep it well-commented and easy to modify further. I want to be able to just change parameters and have a new dice designed without having to fiddle with code. I think that's everything. Let me know if you have any questions.

[Assistant]
Customizable_Dice_02.2.scad:
```
/* Publication Notes */{/*

Customizable Loaded Dice by SavageRodent
Original at: https://www.thingiverse.com/thing:2778633
Last updated: 24/08/2018
Published under: the Creative Commons CC - BY 3.0 licence
Licence details here: https://creativecommons.org/licenses/by/3.0/

*/}
/*********** CUSTAMIZABLE PERAMITORS ************/{
//Note: To make scaling simpler, the dimentions are expressed, directly or inderectly, as fractions of the "dice_size". To see the dimentions as decimals, press F5 (preview) and view the updated, decimal values in the console.

show_cutaway    = 0;   // [ 0=NO 1=YES ]
//show_cutaway is a preview tool. it removes a 1/4 section of the dice so u can inspect the inside. DON'T FORGET to disable (set to "0") befor u render for export.

dice_size       = 20;
//dice_size = (hight, width & depth) of the dice.

wall_thickness = (dice_size/2)*.20;

load_size       = 0;    // %
//load_size = the volume of solid fill inside the dice, causing it to favor laying on a particular side.  0% = no loading, 100% = maximum loading, 200% = solid infill

loaded_number   = 6;    // between 1-6
//loaded_number = the side of the dice to be loaded in favor of

character       = 1;   //[ 0=text, 1=dots_domed, 2=dots_round ]
//characters= the sybols on the sides of the dics dots, numbers, words etc

depth       = (wall_thickness/2)*.5;     //
//depth = how deep the dotos or text charactersare are embossed into the dice. maximum depth is half wall thickness. "depth" is not aplicable to domed dots.

/* dot settings: */{

dot_size        = dice_size*.2;
//dot_size = diamitor of the dot

dot_spaceing    = dice_size/4.1;
//dot_spaceing = the distance from the center of one dot to the center of its nearist neighbor

dot_smooth      = 30;
//dot_smooth = the number of polgons in each dot. higher value = smoother

dice_smooth     = 80;
//dice_smooth  = the number of polgons in cuved parts of the dice. higher value = smoother
/* end of dot settings */}

/* text settings: */{

//side of the dice  1      2      3      4      5      6
txt_charicters  =[ "1",   "2",   "3",   "4",   "5",   "6", ];
//text_character, to change the charictors on the dice simply replace the numbers inside the quotation marks with the whatever numbers, words, symbols etc you want.

// DEFAULT text settings.
// These valus will be used for text ALL charicters unless replased in the custom text settings.

/* font      default    */ fd   = "arile";      // name of a font
/* bold      default    */ bd   = 1;            // bold?    [0=no, 1-yes]
/* italic    default    */ id   = 0;            // italic?  [0=no, 1-yes]
/* spaceing  default    */ spcd = 1;            // size of spacing between charicters
/* size      default    */ sizd = dice_size*.7; // size of text / charicters
/* direction default    */ dd   = 0;            // 0=left-to-right), 1=right-to-left), 3=top-to-bottom 4=bottom-to-top
/* smothness default    */ smod = 40;           //
/* align_h   default    */ ahd  = 0;            // move charicter horazontaly
/* align_v   default    */ avd  = 0;            // move charicter  verticly
/* rotate    default    */ rd   = 0;            // rotate charicter

// CUSTOM text settings.
// To set a custom value for any setting of any charicter simply supliment or replace the default value with one of your chice. Note: Many fonts don't center correctly, so u might want to use the default align_h & v to get the averige center point then tweak any chariters still off center by + or - in custom text settings

//side of the dice 1      2      3      4      5      6
txt_font        =[ fd,    fd,    fd,    fd,    fd,    fd,  ];   // name of a font eg "arile" (include quotation makes)
txt_bold        =[ bd,    bd,    bd,    bd,    bd,    bd   ];   // bold?    [0=no, 1-yes]
txt_italic      =[ id,    id,    id,    id,    id,    id,  ];   // italic?  [0=no, 1-yes]
txt_spaceing    =[ spcd,  spcd,  spcd,  spcd,  spcd,  spcd ];
txt_size        =[ sizd,  sizd,  sizd,  sizd,  sizd,  sizd ];
txt_direction   =[ dd,    dd,    dd,    dd,    dd,    dd   ];   // 0="ltr", 1="rtl", 2="ttb", 3="btt"
txt_smothness   =[ smod,  smod,  smod,  smod,  smod,  smod ];
txt_align_h     =[ ahd+0, ahd+0, ahd+0, ahd+0, ahd+0, ahd+0];
txt_align_v     =[ avd+0, avd+0, avd+0, avd+0, avd+0, avd+0];
txt_rotate      =[ 90,    rd,    rd,    rd,    rd,    90   ];
/*end of text settings */}

//Dule Materal Options:

dule_materal_cut = 0;   //[ 0=NONE, 1=OUTSIDE, 2=INSIDE ]
/*This option enables u to splits the dice into two parts, the inside + characters and the outside.  Simply change the value from "0" too "1" then render and export the STL. Next change the value to "2" then render and export the STL again.*/

/******** end of CUSTAMIZABLE PERAMITORS *******/}

/* miscellaneous */{

hollow          = dice_size-(wall_thickness*2);

load_1_percent = hollow/100;

//                  0      1      2      3
text_direction = ["ltr", "rtl", "ttb", "btt"];
//td = text_direction[dd];   //tdd = text_direction

//                  0      1      2      3
text_direction = ["ltr", "rtl", "ttb", "btt"];
//td = text_direction[dd];   //tdd = text_direction
bo = [" ", "bold: "];       //bold or not bold
it = [" ", "italic "];      //italic or not italic

cut_color=[77/255, 94/255, 210/255];

/* end of miscellaneous */}

/* view customzable peramitors as decimals */{

//The echo() funtions below return the customzable peramitors as decimals that can be viewed in the consele.
echo("********* DIMENTIONS *********");
echo(str("Dice Size           ",dice_size));
echo(str("Wall Thickness   ",wall_thickness));
echo(str("Hollow Size       ",hollow));
echo(str("Load Size          ",(load_size/hollow)*100," %"));
echo(str("Dot Size            ",dot_size));
echo(str("Dot Spaceing     ",dot_spaceing));
echo(str("Depth               ", depth));

/* end of view customzable peramitors */}

/* shapes */{
module outside_shape(){                             //outside shape
intersection() {
sphere(d = dice_size*1.381, $fn = dice_smooth);
cube(size = dice_size, center = true);
}
}

module inside_shape(){                              //inside shape (hollow)
intersection() {
sphere(d = hollow*1.381, $fn = dice_smooth);
cube(size = hollow, center = true);
}
}

module load(){                                      //load shape
translate(v = [0, 0, -hollow/2])
cube(size = [dice_size,dice_size, load_1_percent*load_size], center = true);
}

module dule_materal_shape(){                        //shape used to split the dice
intersection() {
sphere(d = (dice_size*1.381)-(wall_thickness), $fn = dice_smooth);
cube(size = dice_size-((wall_thickness)-.01), center = true);
}
}

module cutaway_shape(){                             //preview tool shape
intersection(){
translate([0,0,-(dice_size*1.1)/2]){
cylinder(h=dice_size*1.1, d=dice_size*1.4, $fn=120);
}
translate([0,0,-(dice_size*1.2)/2]){
cube(dice_size*1.2);  //the cutaway
}
}
}

/* end of shapes */}

/* dots */{

dome_dia = dot_size*1.15;  //diamiter of the sphere that give the dots the inverted dome shape
dome_intecect = sqrt((dome_dia/2)*(dome_dia/2)-((dot_size/2)*(dot_size/2))); //find the distance from the center of sphere were its diamiter = the dot size.

dome_depth = ((dome_dia/2)-dome_intecect);  //

module dot_dome(){
translate([0,0,dice_size/2])
translate([0,0,((dome_dia/2)-dome_depth)])
sphere(d=dome_dia,$fn=dot_smooth);
}

module dot_round(){
translate([0,0,(dice_size/2)-wall_thickness])
cylinder(h=wall_thickness-depth, d=dot_size, $fn=dot_smooth);
}

// dot_cut is a tool used for the dule_materal_cut
module dot_cut(){
translate([0,0,(dice_size/2)-(wall_thickness+.001)])
cylinder(h=wall_thickness*1.1, d=dot_size, $fn=dot_smooth);
}

module dot_depth_cut(){
translate([0,0,(dice_size/2)-depth])
cylinder(h=depth*1.1, d=dot_size, $fn=dot_smooth);
}

/*All the dots on a dice have a postion on a 3x3 matrix (see ilerstration below). Verible x_y_pos hold the x & y value for each of these 9 postions.

0--1--2
3--4--5
6--7--8
*/

ds = dot_spaceing;

//      Postion on 3x3 matrix
//           0          1         2         3         4         5         6         7         8
x_y_pos =[[-ds, ds],[ 0, ds],[ ds, ds],[-ds, 0],[ 0, 0],[ ds, 0],[-ds,-ds],[ 0,-ds],[ ds,-ds]];

grouped_pos = [[4], [0,8], [0,4,8], [0,2,6,8], [0,2,4,6,8], [0,1,2,6,7,8]];     // postion of all dot for each face of the dice

/* end of dots */}

/* Rotation values */{

//     1         2         3         4        5
side=[[180,0,0],[0,270,0],[270,0,0],[90,0,0],[0,90,0]]; //rotation values, used to put each group of dots on its own side.

//rotates all dotes to change waighted number
//dice number: 0          1          2          3          4          5          6
x_y_rot = [[  0,  0], [180,  0], [  0, 90], [ 90,  0], [  0,270], [270,  0], [  0,  0]];
/* end of Rotation values */ }

/* characters all grouped & postioned */{
module characters_dots_domed_all(){
color(cut_color)
rotate( x_y_rot[loaded_number])
for (i =[0:5])         // rotate each group of dots to their own side
rotate(side[i])
for (a =grouped_pos[i]) // generate and postion all dots per a given face of the dice
translate(x_y_pos[a])
dot_dome();
/* end of characters_dots_domed_all */}

module characters_dots_round_all(){
color(cut_color)
rotate( x_y_rot[loaded_number])
for (i =[0:5])         // rotate each group of dots to their own side
rotate(side[i])
for (a =grouped_pos[i]) // generate and postion all dots per a given face of the dice
translate(x_y_pos[a])
dot_round();
/* end of characters_dots_round_all */}

module characters_text_all(){
color(cut_color)
rotate( x_y_rot[loaded_number])
for (i =[0:5])         // rotate each group of dots to their own side
rotate(side[i]){
fo = str(txt_font[i], ": ");// combine font and style into a single string so scad can read it
font_and_style = str(fo, bo[txt_bold[i]], it[txt_italic[i]]);
td = text_direction[txt_direction[i]];   //td = text_direction
rotate([0,0,txt_rotate[i]]){
translate([txt_align_h[i], txt_align_v[i],(dice_size/2)-(wall_thickness/2)]){    //tweak postion of charicters
linear_extrude(height = (wall_thickness/2)-depth){
text(
text        =txt_charicters[i],
size        =txt_size[i],
spacing     =txt_spaceing[i],
font        =font_and_style,
direction   =td,
halign      ="center",
valign      ="center",
$fn         =txt_smothness[i]);
}
}
}
}
/* end of characters_text_all */}
/* end of characters all grouped & postioned */ }
/* cuts all grouped & postioned */{
module cuts_text_all(){
rotate( x_y_rot[loaded_number])
for (i =[0:5]){         // rotate each group of dots to their own side
rotate(side[i]){
fo = str(txt_font[i], ": ");// combine font and style into a single string so scad can read it
font_and_style = str(fo, bo[txt_bold[i]], it[txt_italic[i]]);
td = text_direction[txt_direction[i]];   //tdd = text_direction
rotate([0,0,txt_rotate[i]]){
translate([txt_align_h[i], txt_align_v[i],(dice_size/2)-(wall_thickness/2)]){    //tweak postion of charicters + depth
linear_extrude(height = (wall_thickness/2)*1.1){
text(
text        =txt_charicters[i],
size        =txt_size[i],
spacing     =txt_spaceing[i],
font        =font_and_style,
direction   =td,
halign      ="center",
valign      ="center",
$fn         =txt_smothness[i]);
}
}
}
}
}
/* cuts_text_all */}

module cuts_round_all(){
rotate( x_y_rot[loaded_number])
for (i =[0:5])         // rotate each group of dots to their own side
rotate(side[i])
for (a =grouped_pos[i]) // generate and postion all dots per a given face of the dice
translate(x_y_pos[a])
dot_cut();
/* end of cuts_round_all */}

module cuts_round_depth_all(){
rotate( x_y_rot[loaded_number])
for (i =[0:5])         // rotate each group of dots to their own side
rotate(side[i])
for (a =grouped_pos[i]) // generate and postion all dots per a given face of the dice
translate(x_y_pos[a])
dot_depth_cut();
/* end of cuts_round_depth_all */}

/* end of cuts all grouped & postioned */}
module dice_body(){
color("darkseagreen")
difference(){
outside_shape();
difference(){
inside_shape();
load();
}
}
/* end of cuts_round_all */}

/* dice body and characters combined */{
module dice_text(){
if(dule_materal_cut==0){        //whole
difference(){
color("darkseagreen"){
dice_body();
}
cuts_text_all();
}
characters_text_all();
}
else
if(dule_materal_cut==1){        //outside
difference(){
color("gold"){
difference(){
dice_body();
dule_materal_shape();
}
}
cuts_text_all();
}
}
else
color("white"){                  //inside
intersection(){
dice_body();
dule_materal_shape();
}
characters_text_all();
}
/* end of dice_text */}
module dice_dots_dome(){        //whole
if(dule_materal_cut==0){
difference(){
color("DarkSeaGreen"){
dice_body();
}
characters_dots_domed_all();
}
}
else                            //outside
if(dule_materal_cut==1){
difference(){
color("gold"){
difference(){
dice_body();
dule_materal_shape();
}
}
cuts_round_all();
}
}
else                            //inside
color("white"){
difference(){
union(){
intersection(){
dice_body();
dule_materal_shape();
}
cuts_round_all();
}
characters_dots_domed_all();
}
}
/* end of dice_dots_dome*/ }

module dice_dots_round(){
if(dule_materal_cut==0){        //whole
difference(){
dice_body();
cuts_round_depth_all();
}
}
else
if(dule_materal_cut==1){        //outside
difference(){
color("gold"){
difference(){
dice_body();
dule_materal_shape();
}
}
cuts_round_all();
}
}
else
color("white"){                  //inside
intersection(){
dice_body();
dule_materal_shape();
}
characters_dots_round_all();
}
/* end of dice_dots_round */}
/* end of dice body and characters combined */}
module dice_character_type(){
if(character==0){
dice_text();
}
else
if(character==1){
dice_dots_dome();
}
else
dice_dots_round();
/* end of dice_character_type */}

/* render dice */{
//preview dice with or without cutaway
if(show_cutaway==1){                    //with cutaway
difference(){
dice_character_type();
cutaway_shape();
}
}
else                                    //without cutaway
dice_character_type();
/* end of render dice */}

```


[User]
I'd like to create a customizable origami fox design using OpenSCAD. The provided SCAD file does a good job, but I need to recreate it from scratch with similar parameters.

Here's what I need:

*   **Overall Shape:** The design is essentially a 2D outline of a fox, with inner cutouts that give it an origami look. The outer outline and inner cuts are defined by points specified in the example file, which I will provide as needed.
*   **Customizable Parameters:**
    *   `max_size_in_millimeter`:  This controls the maximum size of the design. The shorter side should be scaled proportionally to maintain the aspect ratio. The range should be something like 20 to 300 mm.
    *   `model_height_in_millimeter`: This sets the thickness of the design, effectively the height for extrusion. This should range from 0.2 to 100 mm, with a step of 0.2.
    *   `outline_size_in_millimeter`: This is the thickness of the outer outline. It should be adjustable from 0.5 to 20 mm, with a step of 0.1.
    *   `inline_size_in_millimeter`: This sets the thickness of the inner cut lines. Range should be 0.5 to 20 mm, step 0.1.
    *   `inline_edge_radius_in_millimeter`: Controls the rounding at the ends of the inner cut lines, ranging from 0 to 5 mm, step 0.1.
    *   `flip_model`: A simple "yes/no" option to mirror the model along the Y axis.

*   **Functionality:**
    *   The design should automatically scale to fit within the `max_size_in_millimeter`, maintaining aspect ratio.
    *   The outer outline should be created by offsetting the main outline, then extruding it.
    *   The inner cut lines should be created by offsetting the inner shapes and then subtracting them from the main shape.
    *   I need the inner line offsets to have rounded ends using the given `inline_edge_radius`.
    *   The `flip_model` option should flip the design around the y-axis and also rotate the design so that it stays in the correct orientation when flipped.

*   **Libraries:** I expect to use only standard OpenSCAD functions for this design. No external libraries are required.

I will provide the point coordinates in a format similar to the one used in the example code. I'd like to have the code generate the 2D shape first and then extrude it.

[Assistant]
customizable_origami_fox.scad:
```
/*
 * Customizable Origami - Fox - https://www.thingiverse.com/thing:2778932
 * by Dennis Hofmann - https://www.thingiverse.com/mightynozzle/about
 * created 2018-02-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.8; //[0.5:0.1:20]

// Roundiness of the ends of the inner outlines.
inline_edge_radius_in_millimeter = 0.7; //[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 = [46, 1089];
A2 = [741, 815];
A3 = [765, 780];
A4 = [1332, 613];
A5 = [1306, 590];
A6 = [1385, 422];
A7 = [1540, 34];
A8 = [1552, 63];
A9 = [1571, 34];
A10 = [1575, 153];
A11 = [1864, 309];
A12 = [1862, 342];
A13 = [1653, 379];
A14 = [1915, 589];
A15 = [1796, 983];
A16 = [1496, 1416];
A17 = [1400, 1139];
A18 = [1032, 1111];
A19 = [1039, 1133];
A20 = [693, 1210];
A21 = [621, 1416];
A22 = [584, 1131];
A23 = [611, 1074];
A24 = [550, 1067];
A25 = [526, 1094];
A26 = [293, 1193];

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

// Inner Points
B1 = [1010, 978];
B2 = [1400, 742];
B3 = [1423, 690];
B4 = [1453, 1138];

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

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

min_x = A1[0];
min_y = A7[1];
max_x = A14[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]
Hey, I'm looking for an OpenSCAD script (or a few, if necessary) to generate custom round belts for a rock tumbler or similar applications. I have the design parameters already and need the script to be parametric.

Specifically, I need these parameters to be customizable:

*   **Belt Thickness (t):** The thickness of the belt, should be able to adjust this.
*   **Pulley 1 Radius (p1):** The radius of the first pulley in mm.
*   **Pulley 2 Radius (p2):** The radius of the second pulley in mm.
*   **Distance between Axels (d):** The center-to-center distance between the two pulleys.
*  **Cross Section:** Either a circle or an octagon for the belt cross-section.

The script should:

1.  Calculate the required belt length based on the pulley radii and the distance between axels using the formula: `2*d + PI*(R+r) + (R-r)*(R-r)/d` (where R is the larger radius, r is the smaller, and d is the distance between axels).
2.  Use `rotate_extrude()` to create the belt.
3.  Create a circular cross section based on the belt thickness if `cross_section` is "circle".
4.  Create an octagonal cross section based on the belt thickness if `cross_section` is "octagon".
5.  Should handle the conversion from calculated belt length to a radius for the rotate_extrude command.
6.  I don't need any extra features (like teeth, etc.) this is just for a basic, simple round belt.

I was thinking of using something like the circle() function for the cross-section. I would be fine if it uses a few libraries to create the polygon for the octagonal cross-section. In fact, if possible, I would like to use the `polygon()` function in the `BOSL2` library instead of `circle()` because I think it might give better control over the circumscribed radius.

Thanks in advance for your help!

[Assistant]
RockTumblerBelt.scad:
```
/*
Round Beld generator
by Bob Marchese
*/

// Belt thickness
t = 3;

// Pulley #1 radius (mm)
p1 = 35;

// Pulley #2 radius (mm)
p2 = 10;

// Distance between axels
d = 75;

// Cross Section
cross_section = "circle"; // [circle,octagon]

/* [Hidden] */
$fn=96;
PI=3.14159265358979323846;
function belt_length(R, r, d) = 2*d + PI*(R+r) + (R-r)*(R-r)/d;

// compute the radius for printing
pr = belt_length(p1,p2,d)/(2*PI);
echo(str("computed belt lenght is ", belt_length(p1,p2,d)));

// generate the torus
if (cross_section == "circle")
{
    echo(str("rotate_extrude() translate([",pr,",0,0]) circle(r=",t/2,");"));
    rotate_extrude() translate([pr,0,0]) circle(r=t/2);
}
else
{
    echo(str("rotate_extrude() translate([",pr,",0,0]) rotate([0,0,22.5]) circle(r=",t/2,",$fn=8);"));
    rotate_extrude() translate([pr,0,0]) rotate([0,0,22.5]) circle(r=t/2, $fn=8);
}

```


[User]
I need a parametric standoff design for mounting circuit boards, similar to the one I saw on Thingiverse by 4iqvmk, but I need it designed from scratch.

Here's what I'm looking for:

**Core Features:**

*   A base with a flat, circular footprint.
*   A cylindrical standoff extending upwards from the center of the base.
*   A central through-hole in both the base and the standoff for mounting with a screw.
*   Several mounting holes in the base, evenly spaced around the central hole.
*   A fillet, or rounded transition, between the base and the standoff.

**Parameters I Need to Control:**

*   `baseDiam`: Diameter of the circular base (in mm).
*   `baseHeight`: Thickness of the base (in mm).
*   `standOffDiam`: Diameter of the standoff cylinder (in mm).
*   `standOffHeight`: Height of the standoff cylinder (in mm).
*   `centerDrillDiam`: Diameter of the central through-hole (in mm).
*  `baseDrillDiam`: Diameter of the mounting holes in the base (in mm).
*   `filletRad`: Radius of the fillet between the base and standoff (in mm).
* `numMountHoles`: the number of mounting holes in the base (an integer value)

**Additional Requirements:**

*   The mounting holes in the base should be equidistant from the center and evenly spaced around the circumference of a circle whose radius is the average of the standoff and base radii.
*   I want the code to generate a single 3D model for preview.
*   I'd like the design to use a reasonable `$fs` and `$fa` for good print quality. Specifically, make sure the code has `$fs = 0.2;` and `$fa = 5;` so I get nicely rounded corners.

Could you generate the OpenSCAD code for this? I don't have any specific libraries I want you to use, just standard OpenSCAD features.

[Assistant]
standoff.scad:
```
/*
 * Configurable Standoff
 *
 * by 4iqvmk, 2018-02-03
 * https://www.thingiverse.com/4iqvmk/about
 *
 * Licenced under Creative Commons Attribution - Share Alike 4.0
 *
 * version 1.00 - initial version
 * version 1.01 - added screw clearance cutaway
*/

/* [Hidden] */

inch2mm = 0.3048/12*1000;
mm2inch = 12/0.3048/1000;
$fs = 0.2;  // Don't generate smaller facets than 0.2 mm
$fa = 5;    // Don't generate larger angles than 5 degrees

/* [Parameters] */

// mm
baseDiam = 25; // [6:2:60]

// mm
baseHeight = 3; // [0:1:30]

// mm
standOffDiam = 8; // [0:1:60]

// mm
standOffHeight = 10; // [0:1:100]

// mm
centerDrillDiam = 2.7; // [0:0.5:10]

// mm
baseDrillDiam = 3.1; // [0:0.5:10]

// mm
filletRad = 6; // [0:0.25:10]

/////////////////////////////////////////////////////////////////////////////
// Calculated values...
/////////////////////////////////////////////////////////////////////////////

maxHeight = max(baseHeight, standOffHeight);

holeRadius = (baseDiam+standOffDiam)/4;

// inner circle template
difference() {
    // flange and surround
    union() {
        ring(centerDrillDiam/2, baseDiam/2, baseHeight);
        ring(centerDrillDiam/2, standOffDiam/2, standOffHeight);
        fillet(baseHeight, standOffDiam/2);
    }

    union() {
        mountingHoles(4, baseDrillDiam, holeRadius);
    }
}

module ring(inner, outer, height) {
    difference() {

        cylinder(h=height, r=outer);
        cylinder(h=4*height, r=inner, center=true);

    }
}

module mountingHoles(num, screwDiam, offsetRadius) {

    // add registration marks
    for (step = [0:num-1]) {
        rotate( a = step*(360/num), v=[0, 0, 1]) {
            translate ( [offsetRadius, 0, 0] ) {
                cylinder(h=maxHeight*4, r=screwDiam/2, center=true);
                translate ([0,0,baseHeight]) {
                    cylinder(h=maxHeight*4, r=2.5*screwDiam/2);
                }
            }
        }
    }
}

module fillet(height, radius) {
    difference() {
        ring((centerDrillDiam/2+radius)/2, radius + filletRad, filletRad+height);

        translate([0, 0, filletRad+height]) {
            torus(filletRad, radius + filletRad);
        }
    }
}

// draw a torus about Z centered on the XY plane
module torus(radius, sweepRad) {
    rotate_extrude(convexity = 10) {
        translate([sweepRad, 0, 0]) {
            circle(radius);
        }
    }
}

```


[User]
Hey, I'm trying to design a header pin block plug for my electronics projects, and I'd like to make it customizable. I've got some specific needs, and I think it'd be great if you could help me generate the OpenSCAD files.

Basically, I want a plug that can hold standard 2.54mm pitch header pins. It needs to have two main parts: an inner plug that the pins actually fit into, and an outer housing that goes around the plug. The user should be able to choose whether to print just the plug, just the housing, or both together.

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

**Pins:**
*   `pin_count`: The total number of pins in the block. (e.g., 7 pins).  Let's say this can range from 1 to 30.
*   `pins_at`: A list of positions that will actually have pins. If empty, all positions will have pins. For instance, if I only wanted pins in positions 1, 4, 5 and 7, I'd have this as `[1, 4, 5, 7]`.
*  `trim_unused_pins`: A boolean option. If true, it should create holes in the plug body for any unused pin positions. If false, the body is solid in those positions.  For the user it should be a "true/false" text choice instead of a boolean.

**Keys:**
*   `keys_a`: A list of pin positions where keys are located on one side of the connector. These could be floating point numbers between 1 and the pin count to allow for fractional spacing if necessary.
*   `keys_b`: Similar to keys_a, but for the other side of the connector.

**Structure:**
*   `plug_height`: Height of the inner plug walls.
*  `housing_height`:  Height of the outer housing walls.
*   `wall_width`: The thickness of the plug and housing walls.
*   `key_size`: The thickness of the keys.

I'd like the code to use standard OpenSCAD, no libraries needed.

The idea is to be able to print either the inner plug alone, the outer housing alone, or both together. When both are printed, the inner plug should fit nicely inside the outer housing with a bit of tolerance. And when printing the full model the plug needs to sit above the housing. The keys are meant to fit into recesses in the housing.

Can you generate the OpenSCAD code for me?

[Assistant]
Header_Pin_Block_Plug.scad:
```
// Create a plug block for header pins

/* [Pins] */

// Show inner plug or outer housing?
part = "both"; // [plug:Inner Plug Only,housing:Outer Housing Only,both:Both Plug & Housing]

// Number of pins in your block
pin_count = 7; // [1:30]

// These positions will have room for pins, leave as [] for all of them
pins_at = [1, 4, 5, 7];

// Allow space for unused pins
trim_unused_pins = "true"; // [true:Remove material for pins to stick through,false:Solid wall where unused pins are]

/* [Keys] */

// Position of keys on one side of connector, can be fractions
keys_a = [ 3, 6];

// Position of keys on the other side
keys_b = [ 2 ];

/* [Structure] */

// Height of the plug walls
plug_height = 5;

// Height of the housing walls
housing_height = 7;

// Width of the walls of the plug & housing
wall_width = 1.5;

// thickness of the keys
key_size = 2;

/* [Hidden] */
realPins = len(pins_at) == 0 ? [1:pin_count] : pins_at;
housingAwall = len(keys_a) == 0 ? wall_width : wall_width + key_size;
housingBwall = len(keys_b) == 0 ? wall_width : wall_width + key_size;
housingBase = housing_height - plug_height;

print_part();

module print_part()
{
    if (part == "plug")
    {
        showPlug();
    }
    else if (part == "housing")
    {
        showHousing();
    }
    else
    {
        translate ([0,0,housingBase+0.2])
        showPlug();
        showHousing();
    }
}

module showPlug()
{
    union()
    {
        difference()
        {
            translate ([2.54 * (pin_count-1) / 2, 0, plug_height/2])
            cube([2.54 * pin_count + wall_width * 2,
                  2.54 + wall_width * 2,
                  plug_height],
                 center=true);
            if (trim_unused_pins == "true")
            {
                emptySpaces();
            }
            pinPositions();
        }
        addkeys();
    }
}

module emptySpaces()
{
    for (i=[1:pin_count])
    {
        // voids for unused pins
        translate([2.54 * (i-1), 0, plug_height/2])
        cube([1, 1, plug_height+2], center=true);
    }
}

module pinPositions()
{
    for (i=realPins)
    {
        // voids for unused pins
        translate([2.54 * (i-1), 0, plug_height/2])
        cube([2.54+.2, 2.54+.2, plug_height+2], center=true);
    }
}

module addkeys()
{
    // translate .1" + wall + key height/2 - connect fudge
    translate([0,2.54/2+ wall_width+ key_size/2 -.1,0]) showkeys(keys_a);
    translate([0,.1-2.54/2-wall_width-key_size/2,0]) showkeys(keys_b);
}

module showkeys(keys)
{
    for (i=keys)
    {
        translate([2.54 * (i-1), 0, plug_height/2])
        cube([1.2,key_size+.2,plug_height],center=true);
    }
}

module showHousing()
{
    difference()
    {
        translate ([2.54 * (pin_count-1) / 2, (housingAwall-housingBwall)/2, housing_height/2])
        cube([2.54 * pin_count + wall_width * 4 + .4,
              2.54 + wall_width*2 + housingAwall + housingBwall + .4,
              housing_height],
              center=true);
        translate([0,0,housingBase])
        union()
        {
            translate ([2.54 * (pin_count-1) / 2, 0, housing_height/2+1])
            cube([2.54 * pin_count + wall_width * 2 + .4,
                  2.54 + wall_width * 2 + .4,
                  housing_height+2],
                  center=true);
            translate([2.54 * (pin_count-1)/2,0,0])
            cube([2.54 * pin_count + .4,
                  2.54 + .4,
                  housing_height+2],
                  center=true);
            removekeys();
        }
    }
}

module removekeys()
{
    // translate .1" + wall + key height/2 - connect fudge
    translate([0,2.54/2+ wall_width+ key_size/2 -.1,0]) keyvoids(keys_a);
    translate([0,.1-2.54/2-wall_width-key_size/2,0]) keyvoids(keys_b);
}

module keyvoids(keys)
{
    for (i=keys)
    {
        translate([2.54 * (i-1), 0, housing_height/2+1])
        cube([1.6,key_size+.4,housing_height+2],center=true);
    }
}

```


[User]
Hey, I'm looking for help creating a parametric design in OpenSCAD. I want to make an optical illusion triangle, similar to the one described on Thingiverse here: [https://www.thingiverse.com/thing:2780187](https://www.thingiverse.com/thing:2780187). It's basically a 2D shape made of outlines and inner cutouts.

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

*   **Overall Size:** I need to specify a maximum size for the longest side of the triangle. The other side should scale proportionally to keep the shape correct. I also need to be able to set the overall height/thickness of the model.
*   **Outline Thickness:** I need to be able to adjust the thickness of the outer edge of the shape, and also the inner cutouts.
*   **Inner Outline Roundness:** It'd be great if I could control the radius of the rounded edges on the inner cutouts.
*   **Flipping:** Also, a simple option to flip the design along the y-axis would be fantastic (to mirror it).

The original design used specific points and polygons for the shape (it looks like a bunch of coordinates in the file), so ideally that can be preserved, but I need these parameters to be adjustable through variables at the start.

I don't think any libraries are needed for this simple shape, as it can all be done with just OpenSCAD primitives like polygons, offsets, and extrudes.

Essentially, I want to be able to adjust the overall size, the thickness of the lines, the roundness of the inside edges, and the orientation of this optical illusion triangle via customizer variables.

[Assistant]
customizable_optical_illusion_triangle.scad:
```
/*
 * Customizable Origami - Optical Illusion Triangle - https://www.thingiverse.com/thing:2780187
 * by Dennis Hofmann - https://www.thingiverse.com/mightynozzle/about
 * created 2018-02-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.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 = [40, 214];
A2 = [141, 42];
A3 = [1817, 43];
A4 = [1923, 216];
A5 = [1079, 1674];
A6 = [878, 1673];

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

// Inner Points
B1 = [777, 214];
B2 = [985, 213];
B3 = [1518, 216];
B4 = [1421, 385];
B5 = [1084, 387];
B6 = [682, 387];
B7 = [535, 386];
B8 = [333, 385];
B9 = [605, 506];
B10 = [1350, 504];
B11 = [982, 562];
B12 = [707, 685];
B13 = [911, 685];
B14 = [1050, 685];
B15 = [1451, 676];
B16 = [1349, 858];
B17 = [1149, 857];
B18 = [604, 857];
B19 = [1051, 1029];
B20 = [911, 1031];
B21 = [708, 1031];
B22 = [978, 1149];
B23 = [1077, 1327];
B24 = [1286, 387];

// Polygons
C1 = [A1, A2, A3, B15, B10, B4, B3, B2, B12, B9, B6, B1];
C2 = [B2, B3, B4, B24, B5];
C3 = [B2, B12, B13, B11, B5];
C4 = [B24, B10, B4];
C5 = [B5, B16, B23, B22, B20, B21, A5, A4, A3, B15, B10, B24];
C6 = [B11, B5, B16, B17, B14];
C7 = [B16, B23, B22, B19, B17];
C8 = [B11, B13, B14];
C9 = [B12, B18, B17, B14, B13];
C10 = [B18, B8, B7, B9, B12];
C11 = [B7, B6, B9];
C12 = [B20, B19, B22];
C13 = [B1, A1, A6, A5, B21, B20, B19, B17, B18, B8, B7, B6];

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

min_x = A1[0];
min_y = A2[1];
max_x = A4[0];
max_y = A5[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'd like to request a parametric OpenSCAD design for a bag clip, similar to what I've been working on, but I need your help generating the code from scratch. I want to have both a "classic" design and an improved version, so I'll describe both.

For both versions, I need the following parameters:

*   `Clip_Length`: The usable length of the clip.
*   `Clip_Height`: The overall height of the clip.
*   `Arm_Thickness`: The thickness of one of the two clip arms.
*   `Extrusion_Width`: The extrusion width of the printer's nozzle (usually the nozzle diameter).
*   `Layer_Height`: The layer height used for printing.
*   `Amount_Noses`: The number of "noses" (and corresponding slots) for gripping the bag.
*   `Noses_Size`: The length that the noses protrude and the depth of the slots.
*   `Opening_Angle`: The maximum angle the clip arms open.
*   `Clip_Overstand`: The distance the clip's clasp needs to bend to snap closed.

I'd like to use `$fn = 64;` for circle resolution.

Here's how the two clip designs should differ:

**"Classic" Design:**

*   The upper arm should be rotated by `-Opening_Angle` and should have rectangular cross sections for the main part of the arm and for the part that hinges to the lower arm. It should include the noses along the length of the arm and have a cylindrical section that serves as the axle
*   The lower arm should have a rectangular cross section for its main body. It should have matching cutouts for the noses and a cylindrical cutout where the axle sits. It should have a snapping mechanism similar to my provided examples.
*   The axle should be a cylinder of diameter `Arm_Thickness`.

**"Improved" Design:**

*   The upper arm is almost identical to the classic design, including the rotation, the rectangular main body, the noses, and a cylinder for the axle portion, but now there are two cylinders that extend beyond the main arm.
*   The lower arm should have a rectangular cross section for its main body. It should have matching cutouts for the noses and an enclosing hollow ring that mates with the axle. It should have a snapping mechanism similar to my provided examples.
*   The axle should now be just a cylindrical extension on the upper arm that mates with a hollow cylindrical section on the lower arm

For both designs, please use a `translate([0,0,Clip_Height/2])` at the top level to center the models vertically and include all the appropriate offsets and extrusion width compensations. Ensure the code is fully parametric, relying on the variables I provided. Also, I need the polyhedron definitions for the "snap" to be correct for the improved design - I've had some issues with those in the past.

Could you generate the OpenSCAD code for both of these designs? I don't need any other files or libraries.

[Assistant]
Customizable_Bag_Clip_Improved.scad:
```
//!OpenSCAD

// The useable length of the Clip
Clip_Length = 100;
// The height of the clip
Clip_Height = 20;
// The thickness of one of the two arms
Arm_Thickness = 6;

// Your extrusion width (Width of the molten plastic trace of your nozzle - Usally your nozzle diameter)
Extrusion_Width = 0.4;
// Your layer height
Layer_Height = 0.2;

// The amount of noses and slots to create
Amount_Noses = 2;
// The length how far a nose is standing out
Noses_Size = 1;

// The angle how far the clip is opened
Opening_Angle = 90;

// How much the clip has to be bowed to snap (I recommend 2mm for PLA and 3mm for ABS)
Clip_Overstand = 2;

//Circle Resolution
$fn = 64;

translate([0,0,Clip_Height/2])
union() {
    // Upper part
    translate([Clip_Length/2 + Arm_Thickness + 1.75*Extrusion_Width, 0, 0])
        rotate([0, 0, -Opening_Angle])
            translate([-Clip_Length/2 - Arm_Thickness - 1.75*Extrusion_Width, 0, 0])
                difference() {
                    union() {
                        translate([(Arm_Thickness + 1.75*Extrusion_Width)/2, Arm_Thickness/2 + Extrusion_Width/4, 0])
                            cube([Clip_Length + Arm_Thickness + 1.75*Extrusion_Width, Arm_Thickness, Clip_Height], center=true);

                        for(i = [1 : 1 : Amount_Noses])
                            translate([0, Extrusion_Width/4, -Clip_Height/2 + i*Clip_Height/(Amount_Noses + 1)])
                                rotate([45,0,0])
                                    cube([Clip_Length, sqrt(2)*Noses_Size, sqrt(2)*Noses_Size], center=true);

                        translate([Clip_Length/2 + Arm_Thickness + 1.75*Extrusion_Width, 0, 0])
                            cylinder(r = Arm_Thickness + Extrusion_Width/4, h = Clip_Height/2-2*Layer_Height, center=true);
                    }

                    translate([Clip_Length/2 + Arm_Thickness + 1.75*Extrusion_Width, 0, 0])
                        cylinder(r = Arm_Thickness/2 + 1.25*Extrusion_Width, h = Clip_Height/2-2*Layer_Height, center=true);

                    translate([Clip_Length/2 + Arm_Thickness + 1.75*Extrusion_Width, 0, 0.375*Clip_Height - Layer_Height/2])
                            cylinder(r = Arm_Thickness + 1.75*Extrusion_Width, h = Clip_Height/4 + Layer_Height, center=true);

                    translate([Clip_Length/2 + Arm_Thickness + 1.75*Extrusion_Width, 0, -0.375*Clip_Height + Layer_Height/2])
                            cylinder(r = Arm_Thickness + 1.75*Extrusion_Width, h = Clip_Height/4 + Layer_Height, center=true);
                }

    // Lower part
    difference() {
        union() {
            translate([(Arm_Thickness + 1.75*Extrusion_Width)/2, -Arm_Thickness/2 - Extrusion_Width/4, 0])
                cube([Clip_Length + Arm_Thickness + 1.75*Extrusion_Width, Arm_Thickness, Clip_Height], center=true);

            translate([Clip_Length/2 + Arm_Thickness + 1.75*Extrusion_Width, 0, 0])
                cylinder(r = Arm_Thickness + Extrusion_Width/4, h = Clip_Height, center=true);

            translate([-(Clip_Length + 5.5*Extrusion_Width)/2, -Arm_Thickness + 1.75*Extrusion_Width, 0])
                cube([5.5*Extrusion_Width, 4*Extrusion_Width, Clip_Height], center=true);

            translate([-Clip_Length/2 - 3.5*Extrusion_Width, 0.75*Extrusion_Width, 0])
                cube([4*Extrusion_Width, 2*Arm_Thickness + 2*Extrusion_Width, Clip_Height], center=true);

            translate([-Clip_Length/2 - 5.5*Extrusion_Width, Arm_Thickness + 1.75*Extrusion_Width , 0])
                polyhedron( points = [[0, 0, -Clip_Height/2], [Clip_Overstand + 5.5*Extrusion_Width, 0, -Clip_Height/2], [5.5*Extrusion_Width, Clip_Overstand, -Clip_Height/2], [0, Clip_Overstand, -Clip_Height/2], [0, 0, Clip_Height/2], [Clip_Overstand + 5.5*Extrusion_Width, 0, Clip_Height/2], [5.5*Extrusion_Width, Clip_Overstand, Clip_Height/2], [0, Clip_Overstand, Clip_Height/2]], faces = [[0,1,2,3], [4,7,6,5], [0,4,5,1], [1,5,6,2], [2,6,7,3], [3,7,4,0]], convexity = 10);
        }

        for(i = [1 : 1 : Amount_Noses])
            translate([Extrusion_Width/4, -Extrusion_Width/4, -Clip_Height/2 + i*Clip_Height/(Amount_Noses + 1)])
                rotate([45,0,0])
                    cube([Clip_Length + Extrusion_Width/2, sqrt(2)*Noses_Size, sqrt(2)*Noses_Size], center=true);

        translate([Clip_Length/2 + Arm_Thickness + 1.75*Extrusion_Width, 0, 0])
            cylinder(r = Arm_Thickness + 1.75*Extrusion_Width, h = Clip_Height/2+2*Layer_Height, center=true);

        translate([-Clip_Length/2 + Clip_Height/4, -Arm_Thickness + 4.5*Extrusion_Width, 0])
            cube([Clip_Height/2, 1.5*Extrusion_Width, Clip_Height], center=true);
    }

    //Axle
    translate([Clip_Length/2 + Arm_Thickness + 1.75*Extrusion_Width, 0, 0])
            cylinder(r = Arm_Thickness/2, h = Clip_Height, center=true);
}
```
Customizable_Bag_Clip_Original.scad:
```
//!OpenSCAD

// The useable length of the Clip
Clip_Length = 100;
// The height of the clip
Clip_Height = 15;
// The thickness of one of the two arms
Arm_Thickness = 6;

// Your extrusion width (Width of the molten plastic trace of your nozzle - Usally your nozzle diameter)
Extrusion_Width = 0.4;
// Your layer height
Layer_Height = 0.2;

// The amount of noses and slots to create
Amount_Noses = 2;
// The length how far a nose is standing out
Noses_Size = 1;

// The angle how far the clip is opened
Opening_Angle = 30;

// How much the clip has to be bowed to snap (I recommend 2mm for PLA and 3mm for ABS)
Clip_Overstand = 2;

//Circle Resolution
$fn = 64;

translate([0,0,Clip_Height/2])
union() {
    // Upper part
    translate([Clip_Length/2 + Arm_Thickness + 1.75*Extrusion_Width, 0, 0])
        rotate([0, 0, -Opening_Angle])
            translate([-Clip_Length/2 - Arm_Thickness - 1.75*Extrusion_Width, 0, 0])
                union() {
                    translate([0,Arm_Thickness/2 + Extrusion_Width/4, 0])
                        cube([Clip_Length, Arm_Thickness, Clip_Height], center=true);

                    for(i = [1 : 1 : Amount_Noses])
                        translate([0, Extrusion_Width/4, -Clip_Height/2 + i*Clip_Height/(Amount_Noses + 1)])
                            rotate([45,0,0])
                                cube([Clip_Length, sqrt(2)*Noses_Size, sqrt(2)*Noses_Size], center=true);

                    translate([(Clip_Length + Arm_Thickness + 1.75*Extrusion_Width)/2, Arm_Thickness/2 + Extrusion_Width/4, 0])
                        cube([Arm_Thickness + 1.75*Extrusion_Width, Arm_Thickness, Clip_Height/2-Layer_Height], center=true);

                    translate([Clip_Length/2 + Arm_Thickness + 1.75*Extrusion_Width, 0, 0])
                        cylinder(r = Arm_Thickness/2, h = Clip_Height, center=true);
                }

    // Lower part
    difference() {
        union() {
            translate([(Arm_Thickness + 1.75*Extrusion_Width)/2, -Arm_Thickness/2 - Extrusion_Width/4, 0])
                cube([Clip_Length + Arm_Thickness + 1.75*Extrusion_Width, Arm_Thickness, Clip_Height], center=true);

            translate([Clip_Length/2 + Arm_Thickness + 1.75*Extrusion_Width, 0, 0])
                cylinder(r = Arm_Thickness + Extrusion_Width/4, h = Clip_Height, center=true);

            translate([-(Clip_Length + 5.5*Extrusion_Width)/2, -Arm_Thickness + 1.75*Extrusion_Width, 0])
                cube([5.5*Extrusion_Width, 4*Extrusion_Width, Clip_Height], center=true);

            translate([-Clip_Length/2 - 3.5*Extrusion_Width, 0.75*Extrusion_Width, 0])
                cube([4*Extrusion_Width, 2*Arm_Thickness + 2*Extrusion_Width, Clip_Height], center=true);

            translate([-Clip_Length/2 - 5.5*Extrusion_Width, Arm_Thickness + 1.75*Extrusion_Width , 0])
                polyhedron( points = [[0, 0, -Clip_Height/2], [Clip_Overstand + 5.5*Extrusion_Width, 0, -Clip_Height/2], [5.5*Extrusion_Width, Clip_Overstand, -Clip_Height/2], [0, Clip_Overstand, -Clip_Height/2], [0, 0, Clip_Height/2], [Clip_Overstand + 5.5*Extrusion_Width, 0, Clip_Height/2], [5.5*Extrusion_Width, Clip_Overstand, Clip_Height/2], [0, Clip_Overstand, Clip_Height/2]], faces = [[0,1,2,3], [4,7,6,5], [0,4,5,1], [1,5,6,2], [2,6,7,3], [3,7,4,0]], convexity = 10);
        }

        for(i = [1 : 1 : Amount_Noses])
            translate([Extrusion_Width/4, -Extrusion_Width/4, -Clip_Height/2 + i*Clip_Height/(Amount_Noses + 1)])
                rotate([45,0,0])
                    cube([Clip_Length + Extrusion_Width/2, sqrt(2)*Noses_Size, sqrt(2)*Noses_Size], center=true);

        translate([Clip_Length/2 + Arm_Thickness + 1.75*Extrusion_Width, 0, 0])
            cylinder(r = Arm_Thickness/2 + 1.25*Extrusion_Width, h = Clip_Height, center=true);

        translate([Clip_Length/2 + Arm_Thickness + 1.75*Extrusion_Width, Arm_Thickness/2, 0])
            cube([2*Arm_Thickness + Extrusion_Width/2, Arm_Thickness + Extrusion_Width/2, Clip_Height/2 + Layer_Height], center=true);

        translate([-Clip_Length/2 + Clip_Height/4, -Arm_Thickness + 4.5*Extrusion_Width, 0])
            cube([Clip_Height/2, 1.5*Extrusion_Width, Clip_Height], center=true);
    }
}
```
Customizeable_Bag_Clip_Improved_Deprecated.scad:
```
//!OpenSCAD

// The useable length of the Clip
Clip_Length = 100;
// The height of the clip
Clip_Height = 20;
// The thickness of one of the two arms
Arm_Thickness = 6;

// Your extrusion width (Width of the molten plastic trace of your nozzle - Usally your nozzle diameter)
Extrusion_Width = 0.4;
// Your layer height
Layer_Height = 0.2;

// The amount of noses and slots to create
Amount_Noses = 2;
// The length how far a nose is standing out
Noses_Size = 1;

// The angle how far the clip is opened
Opening_Angle = 90;

// How much the clip has to be bowed to snap (I recommend 2mm for PLA and 3mm for ABS)
Clip_Overstand = 2;

//Circle Resolution
$fn = 64;

translate([0,0,Clip_Height/2])
union() {
    // Upper part
    translate([Clip_Length/2 + Arm_Thickness + 1.75*Extrusion_Width, 0, 0])
        rotate([0, 0, -Opening_Angle])
            translate([-Clip_Length/2 - Arm_Thickness - 1.75*Extrusion_Width, 0, 0])
                difference() {
                    union() {
                        translate([(Arm_Thickness + 1.75*Extrusion_Width)/2, Arm_Thickness/2 + Extrusion_Width/4, 0])
                            cube([Clip_Length + Arm_Thickness + 1.75*Extrusion_Width, Arm_Thickness, Clip_Height], center=true);

                        for(i = [1 : 1 : Amount_Noses])
                            translate([0, Extrusion_Width/4, -Clip_Height/2 + i*Clip_Height/(Amount_Noses + 1)])
                                rotate([45,0,0])
                                    cube([Clip_Length, sqrt(2)*Noses_Size, sqrt(2)*Noses_Size], center=true);

                        translate([Clip_Length/2 + Arm_Thickness + 1.75*Extrusion_Width, 0, 0])
                            cylinder(r = Arm_Thickness + Extrusion_Width/4, h = Clip_Height/2-2*Layer_Height, center=true);
                    }

                    translate([Clip_Length/2 + Arm_Thickness + 1.75*Extrusion_Width, 0, 0])
                        cylinder(r = Arm_Thickness/2 + 1.25*Extrusion_Width, h = Clip_Height/2-2*Layer_Height, center=true);

                    translate([Clip_Length/2 + Arm_Thickness + 1.75*Extrusion_Width, 0, 0.375*Clip_Height - Layer_Height/2])
                            cylinder(r = Arm_Thickness + 1.75*Extrusion_Width, h = Clip_Height/4 + Layer_Height, center=true);

                    translate([Clip_Length/2 + Arm_Thickness + 1.75*Extrusion_Width, 0, -0.375*Clip_Height + Layer_Height/2])
                            cylinder(r = Arm_Thickness + 1.75*Extrusion_Width, h = Clip_Height/4 + Layer_Height, center=true);
                }

    // Lower part
    difference() {
        union() {
            translate([(Arm_Thickness + 1.75*Extrusion_Width)/2, -Arm_Thickness/2 - Extrusion_Width/4, 0])
                cube([Clip_Length + Arm_Thickness + 1.75*Extrusion_Width, Arm_Thickness, Clip_Height], center=true);

            translate([Clip_Length/2 + Arm_Thickness + 1.75*Extrusion_Width, 0, 0])
                cylinder(r = Arm_Thickness + Extrusion_Width/4, h = Clip_Height, center=true);

            translate([-(Clip_Length + 5.5*Extrusion_Width)/2, -Arm_Thickness + 1.75*Extrusion_Width, 0])
                cube([5.5*Extrusion_Width, 4*Extrusion_Width, Clip_Height], center=true);

            translate([-Clip_Length/2 - 3.5*Extrusion_Width, 0.75*Extrusion_Width, 0])
                cube([4*Extrusion_Width, 2*Arm_Thickness + 2*Extrusion_Width, Clip_Height], center=true);

            translate([-Clip_Length/2 - 5.5*Extrusion_Width, Arm_Thickness + 1.75*Extrusion_Width , 0])
                polyhedron( points = [
                                [0, 0, -Clip_Height/2],
                                [Clip_Overstand + 5.5*Extrusion_Width, 0, -Clip_Height/2],
                                [5.5*Extrusion_Width, Clip_Overstand, -Clip_Height/2],
                                [0, Clip_Overstand, -Clip_Height/2],
                                [0, 0, Clip_Height/2],
                                [Clip_Overstand + 5.5*Extrusion_Width, 0, Clip_Height/2],
                                [5.5*Extrusion_Width, Clip_Overstand, Clip_Height/2],
                                [0, Clip_Overstand, Clip_Height/2]],
                            triangles = [[0,1,2],[0,2,3],[4,7,6],[4,6,5],[0,4,5],[0,5,1],[1,5,6],[1,6,2],[2,6,7],[2,7,3],[3,7,4],[3,4,0]], convexity = 10);
        }

        for(i = [1 : 1 : Amount_Noses])
            translate([Extrusion_Width/4, -Extrusion_Width/4, -Clip_Height/2 + i*Clip_Height/(Amount_Noses + 1)])
                rotate([45,0,0])
                    cube([Clip_Length + Extrusion_Width/2, sqrt(2)*Noses_Size, sqrt(2)*Noses_Size], center=true);

        translate([Clip_Length/2 + Arm_Thickness + 1.75*Extrusion_Width, 0, 0])
            cylinder(r = Arm_Thickness + 1.75*Extrusion_Width, h = Clip_Height/2+2*Layer_Height, center=true);

        translate([-Clip_Length/2 + Clip_Height/4, -Arm_Thickness + 4.5*Extrusion_Width, 0])
            cube([Clip_Height/2, 1.5*Extrusion_Width, Clip_Height], center=true);
    }

    //Axle
    translate([Clip_Length/2 + Arm_Thickness + 1.75*Extrusion_Width, 0, 0])
            cylinder(r = Arm_Thickness/2, h = Clip_Height, center=true);
}
```


[User]
I'd like to create a customizable origami chameleon design in OpenSCAD, similar to the one I saw on Thingiverse. I want to be able to adjust the overall size, height, and the thickness of both the outer and inner lines of the design.

Specifically, the design is based on a 2D outline with several interior cut lines, and the goal is to create a thin, flat model that could be laser cut or 3D printed.

The original design specifies the chameleon's outline using a list of 2D coordinates, as well as lists of coordinates for internal polygons that will be removed (the "cut lines"). I don't need to change any of these coordinates initially, but if possible, I'd like to be able to easily modify them later if I want to tweak the design. I'll need to be able to set these parameters:

*   **`max_size_in_millimeter`**: This should control the size of the longest side of the model, and the shorter side should scale proportionally to maintain the aspect ratio.
*   **`model_height_in_millimeter`**:  The overall height of the model.
*   **`outline_size_in_millimeter`**: The thickness of the outer border/outline of the chameleon.
*   **`inline_size_in_millimeter`**: The thickness of the inner "cut" lines.
*    **`inline_edge_radius_in_millimeter`**: The roundness of the inner cut lines, to add a small fillet.
*   **`flip_model`**: A simple "yes/no" option to flip the entire model across the Y axis.

I will need you to create a new OpenSCAD file using those parameters. I don't require anything beyond the `offset()` and `polygon()` primitives, so no external libraries are needed for this.

[Assistant]
customizable_origami_chameleon.scad:
```
/*
 * Customizable Origami - Chameleon - https://www.thingiverse.com/thing:2780697
 * by Dennis Hofmann - https://www.thingiverse.com/mightynozzle/about
 * created 2018-02-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; //[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 = [224, 639];
A2 = [349, 535];
A3 = [439, 508];
A4 = [587, 322];
A5 = [682, 334];
A6 = [743, 450];
A7 = [731, 519];
A8 = [925, 341];
A9 = [1208, 270];
A10 = [1467, 384];
A11 = [1641, 612];
A12 = [1686, 867];
A13 = [1711, 1042];
A14 = [1714, 1082];
A15 = [1874, 1135];
A16 = [1874, 1566];
A17 = [1714, 1395];
A18 = [1713, 1413];
A19 = [1637, 1565];
A20 = [1561, 1642];
A21 = [1380, 1740];
A22 = [1071, 1741];
A23 = [937, 1601];
A24 = [895, 1458];
A25 = [888, 1367];
A26 = [936, 1266];
A27 = [1025, 1215];
A28 = [1130, 1191];
A29 = [1252, 1240];
A30 = [1321, 1317];
A31 = [1321, 1418];
A32 = [1225, 1515];
A33 = [1071, 1476];
A34 = [1072, 1385];
A35 = [1120, 1369];
A36 = [1101, 1411];
A37 = [1163, 1449];
A38 = [1236, 1390];
A39 = [1175, 1289];
A40 = [1049, 1305];
A41 = [1012, 1421];
A42 = [1053, 1547];
A43 = [1186, 1628];
A44 = [1422, 1566];
A45 = [1467, 1446];
A46 = [1505, 1286];
A47 = [1472, 1226];
A48 = [1333, 1163];
A49 = [1235, 1152];
A50 = [1164, 1156];
A51 = [1162, 1148];
A52 = [1027, 1136];
A53 = [582, 1283];
A54 = [208, 1106];
A55 = [459, 1168];
A56 = [430, 974];
A57 = [569, 1166];
A58 = [755, 1089];
A59 = [749, 1055];
A60 = [862, 995];
A61 = [804, 908];
A62 = [626, 862];
A63 = [524, 863];
A64 = [429, 817];
A65 = [318, 760];

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, A39, A40, A41, A42, A43, A44, A45, A46, A47, A48, A49, A50, A51, A52, A53, A54, A55, A56, A57, A58, A59, A60, A61, A62, A63, A64, A65];

// Inner Points
B1 = [955, 1043];
B2 = [964, 932];
B3 = [1011, 937];
B4 = [1006, 1029];
B5 = [1133, 962];
B6 = [1299, 1010];
B7 = [1168, 987];
B8 = [1134, 995];
B9 = [1133, 1045];
B10 = [895, 1092];
B11 = [1138, 1095];
B12 = [1263, 1069];
B13 = [1379, 1092];
B14 = [1407, 1091];
B15 = [1005, 1135];
B16 = [1332, 1147];
B17 = [385, 549];
B18 = [391, 574];
B19 = [414, 583];
B20 = [425, 556];
B21 = [413, 538];
B22 = [720, 581];
B23 = [332, 627];
B24 = [364, 618];
B25 = [439, 638];
B26 = [495, 554];
B27 = [413, 694];
B28 = [534, 781];
B29 = [605, 747];
B32 = [1068, 410];
B34 = [1486, 612];
B35 = [1601, 822];
B37 = [1401, 803];
B39 = [1725, 1227];
B40 = [558, 538];
B41 = [824, 669];
B42 = [732, 757];
B43 = [1010, 832];
B45 = [1104, 687];
B50 = [1130, 936];
B52 = [1428, 1024];
B53 = [793, 1082];
B58 = [1006, 1046];

// Polygons
C1 = [B2, B3, B4, B1];
C2 = [B5, B8, B7, B6];
C3 = [B24, B18, B17, A2];
C4 = [A2, B17, B21, A3];
C5 = [B21, A3, B26, B20];
C6 = [B26, B25, B19, B20];
C7 = [B25, B24, B18, B19];
C8 = [B11, A51, A50, B12];
C9 = [B10, B58, B15];
C10 = [B15, B58, B4, B3, B43, B9];
C11 = [B9, B43, B42, B45, B50, B5, B8];
C12 = [A1, B23, B27, B28, A64, A65];
C13 = [A64, B28, B29, A62, A63];
C14 = [A1, A2, B24, B23];
C15 = [B23, B27, B28, B29, B22, B25, B24];
C16 = [A3, B40, A5, A4];
C17 = [B40, B22, A7, A6, A5];
C18 = [A3, B40, B22, B25, B26];
C19 = [A62, B42, B41, B32, A9, A8, A7, B22, B29];
C20 = [B32, B34, B35, A13, A12, A11, A10, A9];
C21 = [A61, B2, B1, B53, A60];
C22 = [A60, A59, A58, B53];
C23 = [B42, B45, B34, B32, B41];
C24 = [A62, B42, B43, B3, B2, A61];
C25 = [B45, B34, B35, B37, B6, B5, B50];
C26 = [B37, B52, B39, A14, A13, B35];
C27 = [B37, B6, B12, A50, A49, B16, B13, B52];
C28 = [B52, B39, A17, A18, A19, A46, A47, B14, B13];
C29 = [A46, A19, A20, A21, A44, A45];
C30 = [A44, A22, A21];
C31 = [A22, A43, A44];
C32 = [A43, A23, A22];
C33 = [A43, A23, A24, A42];
C34 = [A42, A24, A25];
C35 = [A25, A42, A41];
C36 = [A41, A26, A25];
C37 = [A41, A40, A28, A27, A26];
C38 = [A40, A39, A30, A29, A28];
C39 = [A39, A38, A31, A30];
C40 = [A38, A32, A31];
C41 = [A33, A37, A38, A32];
C42 = [A33, A36, A37];
C43 = [A36, A35, A34, A33];

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, C28, C29, C30, C31, C32, C33, C34, C35, C36, C37, C38, C39, C40, C41, C42, C43];

min_x = A54[0];
min_y = A9[1];
max_x = A16[0];
max_y = A22[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);
                    }
                }
            }
        }
    }
}

```