[User]
I'd like to create a customizable 2D origami duck, similar to the one described on Thingiverse. I need an OpenSCAD design that allows me to adjust the overall size, height, and outline thicknesses.

Specifically, I need the following parameters:

*   **`max_size_in_millimeter`**:  This will control the maximum dimension of the duck, and the other dimension will scale proportionally. It should have a reasonable range like 20 to 300 mm.
*   **`model_height_in_millimeter`**: The thickness of the extruded duck, probably ranging from 0.2 to 100 mm.
*   **`outline_size_in_millimeter`**: The thickness of the outer edge of the duck, with a range from 0.5 to 20 mm.
*   **`inline_size_in_millimeter`**: The thickness of the inner outlines of the duck with a similar range as the outer outline, 0.5 to 20 mm.
*   **`inline_edge_radius_in_millimeter`**: Controls the roundness of the inner outline ends, with a range from 0 to 5 mm.
*   **`flip_model`**: A yes/no option to mirror the duck along the Y axis.

The design should use a predefined set of points to define the duck's shape (A1 through A24), internal points (B1 through B3), and polygons made from these points (C1 through C14). You'll find the coordinates in the original file - I don't need to copy them all again, right? I want to be able to extrude the outer shape, and then cut out the inner shapes, creating a sort of outline effect. Also, don't forget that the inner outlines should have rounded ends using the `inline_edge_radius`.

The main goal is to have a single, parameterized SCAD file that generates the duck's shape.

Could you generate that for me?

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

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

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

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

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

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

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

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

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

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

// Outer Points
A1 = [63, 262];
A2 = [157, 147];
A3 = [175, 98];
A4 = [231, 63];
A5 = [334, 63];
A6 = [425, 118];
A7 = [473, 226];
A8 = [448, 367];
A9 = [586, 378];
A10 = [995, 603];
A11 = [1121, 601];
A12 = [960, 681];
A13 = [858, 785];
A14 = [623, 822];
A15 = [572, 920];
A16 = [345, 920];
A17 = [517, 886];
A18 = [456, 771];
A19 = [266, 670];
A20 = [166, 518];
A21 = [207, 377];
A22 = [311, 247];
A23 = [298, 223];
A24 = [221, 204];

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

// Inner Points
B1 = [226, 140];
B2 = [502, 546];
B3 = [743, 675];

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

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

min_x = A1[0];
min_y = A4[1];
max_x = A11[0];
max_y = A15[1];

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

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

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

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

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

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

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

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

```


[User]
Hey, I'm looking to generate some cylindrical poles for a few projects I'm working on. I'd like an OpenSCAD file (or files, if it makes sense) that can do this, and be easily customizable.

Specifically, I need to be able to set the radius of the cylinder, the height (or length) of the cylinder, and the number of cylinders to generate. The cylinders should be generated in a row along the y-axis, so each subsequent cylinder is placed immediately following the previous one, with a small gap. I'd like that gap to be based on the radius of the cylinder - maybe 3 times the radius would be good. Also, each cylinder should be oriented vertically; that is, its length axis should be along the z-axis. I need to be able to specify the overall length of these poles, independent of a particular radius, which means I need to be able to rotate them 90 degrees around the x axis.

Could you generate the SCAD file(s) for me? I don't have any existing files to start with. Thanks!

[Assistant]
cylinder.scad:
```
$fn = 32;

radius = 1.5;
height = 40;

num = 1;

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

    translate([0, i*(radius * 3),0])
    rotate([0,90,0])
    cylinder(r=radius, h=height);

}
```


[User]
I'd like to create a customizable 2D origami design of a Pac-Man Ghost, similar to the one I saw on Thingiverse. I need an OpenSCAD file that will let me control the following parameters:

*   **Max Size:** The maximum length of the longer side of the ghost. The other side should scale proportionally. I need to be able to specify this in millimeters.
*   **Model Height:** The overall thickness/height of the 2D model, also in millimeters.
*   **Outline Size:** The thickness of the outer outline of the ghost, in millimeters.
*   **Inline Size:** The thickness of the inner outlines, also in millimeters.
*   **Inline Edge Radius:** The roundness of the ends of the inner outlines, specified in millimeters.
*   **Flip Model:** A boolean option (yes/no) to flip the model horizontally.

The design should have the following specific shape (the coordinates are just for reference and I don't need to enter them, but the proportions should match):

**Outer Points:**
A1 = [64, 928]; A2 = [64, 448]; A3 = [128, 448]; A4 = [128, 256]; A5 = [192, 256]; A6 = [192, 192]; A7 = [256, 192]; A8 = [256, 128]; A9 = [384, 128]; A10 = [384, 64]; A11 = [640, 64]; A12 = [640, 128]; A13 = [736, 128]; A14 = [736, 192]; A15 = [800, 192]; A16 = [800, 256]; A17 = [864, 256]; A18 = [864, 320]; A19 = [864, 384]; A20 = [864, 448]; A21 = [928, 448]; A22 = [928, 928]; A23 = [864, 928]; A24 = [864, 864]; A25 = [800, 864]; A26 = [800, 800]; A27 = [736, 800]; A28 = [736, 864]; A29 = [672, 864]; A30 = [672, 928]; A31 = [576, 928]; A32 = [576, 800]; A33 = [448, 800]; A34 = [448, 928]; A35 = [320, 928]; A36 = [320, 864]; A37 = [256, 864]; A38 = [256, 800]; A39 = [192, 800]; A40 = [192, 864]; A41 = [128, 864]; A42 = [128, 928];

**Inner Points:**
B1 = [256, 320]; B2 = [320, 320]; B3 = [320, 256]; B4 = [448, 256]; B5 = [448, 320]; B6 = [512, 320]; B7 = [512, 384]; B8 = [512, 512]; B9 = [448, 512]; B10 = [448, 576]; B11 = [320, 576]; B12 = [320, 512]; B13 = [256, 512]; B14 = [384, 384]; B15 = [384, 512]; B16 = [672, 256]; B17 = [672, 320]; B18 = [608, 320]; B19 = [608, 512]; B20 = [672, 512]; B21 = [672, 576]; B22 = [800, 576]; B23 = [800, 512]; B24 = [800, 320]; B25 = [736, 384]; B26 = [736, 512]; B27 = [864, 512];

**Polygons to Cut:**
C1 = [B15, B14, B7, B6, B5, B4, B3, B2, B1, B13, B12, B11, B10, B9];
C2 = [B24, A16, B16, B17, B18, B19, B20, B21, B22, B23, B26, B25, A19, A18];

The code should create a solid object with the outer shape. It should then cut away the inner polygons, creating outlines with the specified thickness and rounded edges.

I don't need any external libraries, just the base OpenSCAD functionality.

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

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

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

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

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

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

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

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

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

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

// Outer Points
A1 = [64, 928];
A2 = [64, 448];
A3 = [128, 448];
A4 = [128, 256];
A5 = [192, 256];
A6 = [192, 192];
A7 = [256, 192];
A8 = [256, 128];
A9 = [384, 128];
A10 = [384, 64];
A11 = [640, 64];
A12 = [640, 128];
A13 = [736, 128];
A14 = [736, 192];
A15 = [800, 192];
A16 = [800, 256];
A17 = [864, 256];
A18 = [864, 320];
A19 = [864, 384];
A20 = [864, 448];
A21 = [928, 448];
A22 = [928, 928];
A23 = [864, 928];
A24 = [864, 864];
A25 = [800, 864];
A26 = [800, 800];
A27 = [736, 800];
A28 = [736, 864];
A29 = [672, 864];
A30 = [672, 928];
A31 = [576, 928];
A32 = [576, 800];
A33 = [448, 800];
A34 = [448, 928];
A35 = [320, 928];
A36 = [320, 864];
A37 = [256, 864];
A38 = [256, 800];
A39 = [192, 800];
A40 = [192, 864];
A41 = [128, 864];
A42 = [128, 928];

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

// Inner Points
B1 = [256, 320];
B2 = [320, 320];
B3 = [320, 256];
B4 = [448, 256];
B5 = [448, 320];
B6 = [512, 320];
B7 = [512, 384];
B8 = [512, 512];
B9 = [448, 512];
B10 = [448, 576];
B11 = [320, 576];
B12 = [320, 512];
B13 = [256, 512];
B14 = [384, 384];
B15 = [384, 512];
B16 = [672, 256];
B17 = [672, 320];
B18 = [608, 320];
B19 = [608, 512];
B20 = [672, 512];
B21 = [672, 576];
B22 = [800, 576];
B23 = [800, 512];
B24 = [800, 320];
B25 = [736, 384];
B26 = [736, 512];
B27 = [864, 512];

// Polygons
C1 = [B15, B14, B7, B6, B5, B4, B3, B2, B1, B13, B12, B11, B10, B9];
C2 = [B24, A16, B16, B17, B18, B19, B20, B21, B22, B23, B26, B25, A19, A18];

cut_polygons = [C1, C2];

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

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

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

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

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

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

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

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

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

```


[User]
I'd like to create a customizable 2D origami swan design using OpenSCAD, similar to the one I saw on Thingiverse (thing:2661542).

Here's what I'm looking for:

**Overall Structure:**

*   The design should be based on a series of connected polygons, some of which are outlined.
*   The user should be able to control the overall size, height, and outline thicknesses.
*   The design will be created via linear extrusion of a 2D polygon shape.

**Key Parameters:**

*   `max_size_in_millimeter`: The maximum dimension (longest side) of the swan, with the other dimension resizing proportionally. I'd like to be able to set this between 20 and 300 mm.
*   `model_height_in_millimeter`: The overall height of the extruded shape. Should be adjustable, maybe from 0.2 to 100 mm with a step of 0.2 mm.
*   `outline_size_in_millimeter`: The thickness of the outer outline, adjustable from 0.5 to 20 mm with a step of 0.1 mm
*  `inline_size_in_millimeter`: The thickness of the inner outlines (these form the inner folding lines), adjustable from 0.5 to 20mm with a step of 0.1.
*  `inline_edge_radius_in_millimeter`: The radius of the rounded edges of the inner outlines, adjustable from 0 to 5 with a step of 0.1
*   `flip_model`: A simple "yes" or "no" toggle to mirror the model along its vertical axis (or along the x axis in this case, since its 2D.)

**Polygon Data:**

The design uses specific point coordinates to define the outer shape and inner folding lines.  I'll provide those points, grouped into `outline` and `cut_polygons` lists:

```
// Outer Points
A1 = [142, 399];
A2 = [133, 369];
A3 = [173, 311];
A4 = [115, 174];
A5 = [276, 20];
A6 = [435, 45];
A7 = [489, 273];
A8 = [224, 819];
A9 = [328, 718];
A10 = [576, 669];
A11 = [914, 798];
A12 = [1041, 910];
A13 = [950, 987];
A14 = [1019, 1033];
A15 = [705, 1235];
A16 = [226, 1235];
A17 = [12, 1022];
A18 = [31, 775];
A19 = [424, 276];
A20 = [402, 103];
A21 = [290, 81];
A22 = [229, 301];
A23 = [177, 390];

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

// Inner Points
B1 = [166, 370];
B2 = [196, 305];
B3 = [183, 177];
B4 = [69, 855];
B5 = [119, 1080];
B6 = [209, 847];
B7 = [325, 821];
B8 = [531, 947];
B9 = [593, 1134];
B10 = [894, 1025];

// Polygons
C1 = [A2, B1, A23, A1];
C2 = [B1, B2, A22, A23];
C3 = [B1, A2, A3, B2];
C4 = [A3, A4, B3, B2];
C5 = [A4, A5, B3];
C6 = [A5, A21, A22, B2, B3];
C7 = [A5, A20, A21];
C8 = [A5, A20, A6];
C9 = [A20, A19, A7, A6];
C10 = [A19, A18, B4, A7];
C11 = [A7, A8, B6, B4];
C12 = [A18, A17, B4];
C13 = [B4, B6, B5, A17];
C14 = [A8, A9, B7, B5, B6];
C15 = [A9, A10, B7];
C16 = [A10, A11, A12];
C17 = [A10, A12, B8, B7];
C18 = [A12, A13, B10, A15, B9, B8];
C19 = [A13, A14, B10];
C20 = [A14, A15, B10];
C21 = [B9, B5, A16, A15];
C22 = [B5, A17, A16];
C23 = [B5, B7, B8, B9];

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

**Scaling:**

*   The design needs to scale proportionally, so the shortest side scales based on the longest one (set using `max_size_in_millimeter`).  I think the code in the existing SCAD adjusts the outline sizes correctly based on the x and y scaling factor.

**Module Structure**

I'd like the design to be generated using a module called `create()` (I can call it something different later, this seems sensible). This function should handle all the offsets, polygons, and linear extrusion.

**Additional Notes:**

*   I prefer to have `$fn=32` set for the smooth curves.
*   I think I understand that the first offset of 0 for the outline is a trick to avoid extra outer edges, but I'd like to double check with you.
*   I think I understand the `difference()` and the inner `offset()` calls, but if you can give me a quick description to be sure that would be great.
*   It'd be helpful if the code was well-commented and easy to understand, especially with regards to the transformations.
*   I'm not using any libraries, but if you have any helper modules that might be good to use, that would be great.

Let me know if you need more information!

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

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

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

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

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

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

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

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

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

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

// Outer Points
A1 = [142, 399];
A2 = [133, 369];
A3 = [173, 311];
A4 = [115, 174];
A5 = [276, 20];
A6 = [435, 45];
A7 = [489, 273];
A8 = [224, 819];
A9 = [328, 718];
A10 = [576, 669];
A11 = [914, 798];
A12 = [1041, 910];
A13 = [950, 987];
A14 = [1019, 1033];
A15 = [705, 1235];
A16 = [226, 1235];
A17 = [12, 1022];
A18 = [31, 775];
A19 = [424, 276];
A20 = [402, 103];
A21 = [290, 81];
A22 = [229, 301];
A23 = [177, 390];

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

// Inner Points
B1 = [166, 370];
B2 = [196, 305];
B3 = [183, 177];
B4 = [69, 855];
B5 = [119, 1080];
B6 = [209, 847];
B7 = [325, 821];
B8 = [531, 947];
B9 = [593, 1134];
B10 = [894, 1025];

// Polygons
C1 = [A2, B1, A23, A1];
C2 = [B1, B2, A22, A23];
C3 = [B1, A2, A3, B2];
C4 = [A3, A4, B3, B2];
C5 = [A4, A5, B3];
C6 = [A5, A21, A22, B2, B3];
C7 = [A5, A20, A21];
C8 = [A5, A20, A6];
C9 = [A20, A19, A7, A6];
C10 = [A19, A18, B4, A7];
C11 = [A7, A8, B6, B4];
C12 = [A18, A17, B4];
C13 = [B4, B6, B5, A17];
C14 = [A8, A9, B7, B5, B6];
C15 = [A9, A10, B7];
C16 = [A10, A11, A12];
C17 = [A10, A12, B8, B7];
C18 = [A12, A13, B10, A15, B9, B8];
C19 = [A13, A14, B10];
C20 = [A14, A15, B10];
C21 = [B9, B5, A16, A15];
C22 = [B5, A17, A16];
C23 = [B5, B7, B8, B9];

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

min_x = A17[0];
min_y = A5[1];
max_x = A12[0];
max_y = A15[1];

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

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

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

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

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

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

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

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

```


[User]
Okay, I'd like to create a parametric dog generator in OpenSCAD. I'd like to be able to control a number of aspects of the dog's geometry, and also have the option of creating a number of dogs at once, either using the same parameters or with random values.

Here's a breakdown of what I need:

**Core Dog Module:**

*   I need a module called `dog` that takes the following parameters: `r_head`, `l_head`, `lift_head`, `up_neck`, `r_body`, `l_body`, `r_leg_low`, `l_leg`, `out_leg`, `l_feet`, `r_tail`, `l_tail`, `pos_eye`, `r_eye`, `thick_ear`, and `r_ear`. These parameters will control the dimensions of the various parts of the dog. They represent the radius of the head, length of the head, lift of the head, length of the neck, radius of the body, length of the body, radius of the bottom of the legs, length of the legs, how far the legs are out to the side, length of the feet, radius of the tail, length of the tail, position of the eyes along the head's length, radius of the eye, thickness of the ears, and radius of the ears.
*   The dog should be constructed using spheres for the head, body, legs, and tail. The legs and tail should be created with hull operations between the various body parts. The ears should be created as slightly rotated cubes with a subtraction to create the ear shape. The eyes should also be spheres.
*   The core module should perform all its joins in such a way that the whole dog is one single contiguous object.  I don't want separate pieces floating around, I want to be able to print the entire thing as one object.

**Base Plate Option:**
*   I need an option to include a base plate under the dog. This should be controlled by a variable `PrintBase` (1 for yes, 0 for no). The base plate should be a simple rectangle with rounded edges. The size of this rectangle should be defined by variables `basex`, `basey`, and `basethick`, controlling the x/y size and the thickness of the base.

**Dog Generation Modules:**

*   I need a module called `standard_dog()` that generates a single dog using the current values of the global parameters, i.e. the parameters I initially defined.
*   I need a module called `random_dog()` that generates a single dog using randomly generated values for all of those dog parameters listed above. It should choose these values within reasonable ranges (similar to how the example code does it, using `rands()`).
*   I need a module called `randomdogs(xx,yy)` that generates a grid of `xx` by `yy` random dogs, each with its own set of random parameters. This should use `translate()` to offset each dog in the grid.  I would like a baseplate generated under each individual dog, which is a good reason to have a baseplate generated inside the `dog` function.

**Main Logic:**

*   The program should use a variable `type` to determine what to generate. The options for `type` should be: `"configurable_dog"`, `"random_dog"`, `"9_random_dogs"`, and `"16_random_dogs"`.
*   If `type` is `"configurable_dog"`, the program should call `standard_dog()`.
*   If `type` is `"random_dog"`, the program should call `random_dog()`.
*   If `type` is `"9_random_dogs"`, the program should call `randomdogs(3,3)`.
*   If `type` is `"16_random_dogs"`, the program should call `randomdogs(4,4)`.
*   I'm okay with the default variable values being identical to those in the example file.
*   I would like to be able to chamfer the bottom of the baseplates using some parameters as shown in the example file.

I think that's it. Let me know if you have any questions or need more details. I expect that you'll need to create several custom modules for the dogs.

[Assistant]
puppy_VB.scad:
```
type="9_random_dogs"; //[configurable_dog,random_dog, 9_random_dogs,16_random_dogs]

//should we have a base?
PrintBase=1; //[1,0]

//radius head
r_head=8;

//length head
l_head=10;

//lift of the head -> r_head*.7;
lift_head=5.6;

//neck length
up_neck=15;

//radius body
r_body=7;

//length body
l_body=18;

//leg radius at bottom
r_leg_low=5;

//length legs
l_leg=18;

//legs to the outside -> l_leg/3
out_leg=6;

//length feet ->
l_feet=4.5;

//radius tail
r_tail=3;

//length tail
l_tail=20;

//position of the eye
pos_eye=.15;

//radius of the eye
r_eye=r_head/2;

//thickness of the ears
thick_ear=3;

//radius of ears -> r_head*.7;
r_ear=5.6;

/* [Hidden] */
//-------------------------------------------------------------------------------
/*
Configurable dog pack
Version B, December 2017
Written by MC Geisler (mcgenki at gmail dot com)

You need configurable dogs? You have configurable dogs. Either one or nine, you decide.
Use it to create mini or big dog sculptures!

Have fun!

License: Attribution 4.0 International (CC BY 4.0)

You are free to:
    Share - copy and redistribute the material in any medium or format
    Adapt - remix, transform, and build upon the material
    for any purpose, even commercially.
*/

basex=60;
basey=40;
basethick=5;

module dog(r_head,l_head,lift_head,up_neck,r_body,l_body,r_leg_low,l_leg,out_leg,l_feet,r_tail,l_tail,pos_eye,r_eye,thick_ear,r_ear)
{
	r_neck=r_head*.7;
	forward_neck=5;
	straight_neck=.3;
	leg_mid_percent=.3;
	Cutoffleg_percent=.5;
	r_mid_tail_percent=1.3;
	tail_mid_percent=.35;
	tail_low_percent=.21;

	dummy_max_body_extent=l_head+forward_neck+l_body+out_leg+l_tail+r_head+r_tail;

	module body(pos)
	{
		translate([pos*l_body/2,0,0])
			sphere(r=r_body,center=true);
	}
	module front_body()
	{
		body(1);
	}
	module back_body()
	{
		body(-1);
	}
	module mid_neck(shift)
	{
		translate([l_body/2+forward_neck*shift,0,up_neck*shift])
			sphere(r=r_neck,center=true);
	}
	module head(pos)
	{
		translate([l_body/2+forward_neck+pos*l_head,0,up_neck+lift_head*pos])
			sphere(r=r_head,center=true);
	}
	module back_head()
	{
		head(0);
	}
	module front_head()
	{
		head(1);
	}
	module eye(pos)
	{
		translate([l_body/2+forward_neck+pos_eye*l_head,pos*r_eye*.7,up_neck+r_head*1.1+lift_head*pos_eye])
			sphere(r=r_eye,center=true);
	}
	module earpart(pos)
	{
		translate([l_body/2+forward_neck-.5*l_head,pos*r_head/2,up_neck+r_head-lift_head*.5])
			rotate([45,35,-20*pos])
				cube(r_ear,center=true);
	}
	module ear(pos)
	{
		length=sqrt(l_head*l_head+lift_head*lift_head);
		$fn=25;

		difference()
		{
			earpart(pos);
			translate([thick_ear*l_head/length,0,lift_head*thick_ear/length])
				earpart(pos);
		}
	}
	module leg(out_percent,dirx,diry)
	{
		translate([(l_body/2+out_leg*out_percent)*dirx,((r_body-r_leg_low)+out_leg*out_percent)*diry,-l_leg*out_percent])
			sphere(r=r_leg_low,center=true);
	}
	module tail(pos,radiusfactor)
	{
		translate([-l_body/2-l_tail*pos/2,0,l_tail*pos])
			sphere(r=r_tail*radiusfactor,center=true);
	}

	//---------------------------------

	module specific_dog()
	{
		//body
		hull()
		{
			back_body();
			front_body();
		}

		//head
		hull()
		{
			back_head();
			front_head();
		}

		//lower neck
		hull()
		{
			front_body();
			mid_neck(.5-straight_neck/2);
		}
		//middle neck
		hull()
		{
			mid_neck(.5-straight_neck/2);
			mid_neck(.5+straight_neck/2);
		}
		//upper neck
		hull()
		{
			mid_neck(.5+straight_neck/2);
			back_head();
		}

		module complete_leg(dirx,diry)
		{
			//foot
			hull()
			{
				leg(1,dirx,diry);
				translate([l_feet,0,0])
					leg(1,dirx,diry);
			}
			//lower leg
			hull()
			{
				leg(1,dirx,diry);
				leg(leg_mid_percent,dirx,diry);
			}
			//upper leg
			hull()
			{
				leg(leg_mid_percent,dirx,diry);
				body(dirx);
			}
		}
		//four legs
		for (i = [-1, 1])
		{
			for (j = [-1, 1])
			{
				complete_leg(i,j);
			}
		}

		//upper tail
		hull()
		{
			tail(1,1);
			tail(tail_mid_percent,1);
		}
		//mid tail
		hull()
		{
			tail(tail_mid_percent,1);
			tail(tail_low_percent,r_mid_tail_percent);
		}
		//lower tail
		hull()
		{
			tail(tail_low_percent,r_mid_tail_percent);
			back_body();
		}
		//ear
		ear(-1);
		ear(1);
		//eye
		eye(1);
		eye(-1);
	}
	//---------------------------------

	difference()
	{
		translate([0,0,l_leg+r_leg_low*Cutoffleg_percent])
			specific_dog();
		translate([0,0,-dummy_max_body_extent/2])
			cube([dummy_max_body_extent,dummy_max_body_extent,dummy_max_body_extent],center=true);
	}

    if(PrintBase==1)
    {
        scalingx=(basex+2*basethick)/basex;
        scalingy=(basey+2*basethick)/basey;
        translate([0,0,-basethick/2])
                scale([1,1,-1])
                    linear_extrude(height = basethick, center = true, scale=[scalingx,scalingy])
                    square([basex,basey],center=true);

        chamfer=1;
        goalx=(basex+2*basethick-chamfer);
        goaly=(basey+2*basethick-chamfer);
        chamferx=(basex+2*basethick)/goalx;
        chamfery=(basey+2*basethick)/goaly;

        translate([0,0,-basethick-chamfer/2])
                linear_extrude(height = chamfer, center = true, scale=[chamferx,chamfery])
                    square([goalx,goaly],center=true);
    }
}

module random_dog()
{
	r_head=rands(4,10,1)[0]; //8;
	l_head=rands(2,12,1)[0]; //10;
	lift_head=rands(3,12,1)[0]; //.7;
	up_neck=rands(10,30,1)[0]; //15
	r_body=rands(5,10,1)[0]; //7
	l_body=rands(7,20,1)[0]; //18
	r_leg_low=rands(8,12,1)[0]/2; //5
	l_leg=rands(8,26,1)[0]; //18
	out_leg=l_leg/6*rands(0,3,1)[0];
	l_feet=l_leg/8*rands(0,3,1)[0];
	r_tail=rands(3,7,1)[0]/2; //3
	l_tail=rands(5,30,1)[0]; //20
	pos_eye=.15;
	r_eye=r_head/2;
	thick_ear=3;
	r_ear=r_head/2;

	dog(r_head,l_head,lift_head,up_neck,r_body,l_body,r_leg_low,l_leg,out_leg,l_feet,r_tail,l_tail,r_eye,pos_eye,thick_ear,r_ear);
}

module standard_dog()
{

	dog(r_head,l_head,lift_head,up_neck,r_body,l_body,r_leg_low,l_leg,out_leg,l_feet,r_tail,l_tail,pos_eye,r_eye,thick_ear,r_ear);
}

//---------------------------------------

module randomdogs(xx,yy)
{
    for (x = [0:xx-1])
    {
        for (y = [0:yy-1])
        {
         //     $fn=rands(5,40,1)[0]; //40;
        /*
                r_head=rands(4,10,1)[0]; //8;
                l_head=rands(2,12,1)[0]; //10;
                lift_head=rands(3,12,1)[0]; //.7;
                up_neck=rands(10,30,1)[0]; //15
                r_body=rands(5,10,1)[0]; //7
                l_body=rands(7,20,1)[0]; //18
                r_leg_low=rands(8,12,1)[0]/2; //5
                l_leg=rands(8,26,1)[0]; //18
                out_leg=l_leg/6*rands(0,3,1)[0];
                l_feet=l_leg/8*rands(0,3,1)[0];
                r_tail=rands(3,7,1)[0]/2; //3
                l_tail=rands(5,30,1)[0]; //20
        */

                translate([x*basex,y*basey,0])
                    random_dog();
        }
    }
}

if (type=="9_random_dogs")
{
    randomdogs(3,3);
}

if (type=="16_random_dogs")
{
    randomdogs(4,4);
}

if (type=="configurable_dog")
{
    $fn=22;//40

    //get values from above (configuration possibility)
    standard_dog();
}

if (type=="random_dog")
{
    $fn=rands(5,40,1)[0]; //40;
    random_dog();
}

```


[User]
I'd like to create a customizable 2D origami dolphin design using OpenSCAD. The design should allow for adjustments to the overall size, height, and the thickness of both the outer and inner outlines.

Here's a breakdown of what I'm looking for:

*   **Overall Shape:** The dolphin's outline is defined by a series of 26 points (A1 to A26). There are also some inner cut-out shapes defined using points B1-B8 which are organized into polygons. These polygons (C1-C9) represent areas to be cut out from the main outline. Please encode these polygons as hardcoded polygon data into the generated code. I've included the exact points as `A1 = [60, 524];` (and so on) in the attached SCAD file.
*   **Customization:**
    *   **Maximum Size:** The design should be scalable based on a `max_size_in_millimeter` parameter, which controls the longest side. The shorter side should scale proportionally. I'd like to specify this in millimeters as a parameter.
    *   **Model Height:** The overall height of the extruded 2D design should be adjustable via `model_height_in_millimeter`.
    *   **Outline Thickness:** The thickness of the outer line should be controlled by `outline_size_in_millimeter`.
    *   **Inner Line Thickness:** The thickness of the inner lines (the cutouts) should be defined by `inline_size_in_millimeter`.
    *   **Inner Line End Roundness:** The roundness of the edges of the inner cutouts should be controlled by `inline_edge_radius_in_millimeter`.
    *   **Mirror:** There should be an option to mirror the dolphin shape via a `flip_model` parameter (either "yes" or "no").
*   **File Structure:** I would like a single file with modules.
*   **Units:** Everything should be defined in millimeters.
*   **Functionality:** The design should use `linear_extrude` to create the 3D model from the 2D shapes. I'd like to see use of the `offset()` command to create the inner and outer outlines, and `polygon()` command to render the shapes. The `difference()` module should be used to cut out the inner shapes. I would like to see use of `resize()` to scale the model.

Could you generate the OpenSCAD code for this?

[Assistant]
customizable_origami_dolphin.scad:
```
/*
 * Customizable Origami - Dolphin - https://www.thingiverse.com/thing:2664065
 * by Dennis Hofmann - https://www.thingiverse.com/mightynozzle/about
 * created 2017-11-23
 * 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 = 2.1; //[0.5:0.1:20]

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

// Roundiness of the ends of the inner outlines.
inline_edge_radius_in_millimeter = 0.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 = [60, 524];
A2 = [169, 481];
A3 = [229, 348];
A4 = [598, 171];
A5 = [757, 15];
A6 = [755, 182];
A7 = [955, 198];
A8 = [1186, 329];
A9 = [1335, 518];
A10 = [1357, 579];
A11 = [1561, 702];
A12 = [1383, 659];
A13 = [1245, 692];
A14 = [1285, 598];
A15 = [1151, 511];
A16 = [992, 466];
A17 = [909, 471];
A18 = [984, 635];
A19 = [832, 545];
A20 = [737, 479];
A21 = [626, 502];
A22 = [620, 610];
A23 = [527, 523];
A24 = [438, 541];
A25 = [178, 564];
A26 = [60, 553];

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 = [652, 418];
B2 = [728, 387];
B3 = [895, 444];
B4 = [695, 451];
B5 = [903, 460];
B6 = [1337, 568];
B7 = [562, 444];
B8 = [271, 524];

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

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

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

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

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

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

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

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

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

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

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

```


[User]
Hey, I'm working on a paste extruder project and need some custom luer lock adapters. I've been modifying an existing design, but it's not as flexible as I need.

I'd like a parametric design that I can tweak for different nozzle sizes. Basically, I need a cylinder with a luer lock connection on one end and a nozzle on the other, and I want to be able to easily change the inner and outer diameters of the nozzle, as well as the nozzle's length.

Here's what I'm thinking:

*   **Nozzle:** The nozzle itself will be a simple cylinder. I need parameters for:
    *   `Inside_Radius`: The inner radius of the nozzle (for the paste).
    *   `Outside_Radius`: The outer radius of the nozzle.
    *   `Nozzle_Length`: The length of the nozzle.

*   **Luer Lock:**  The luer lock connector should match standard dimensions. The original design I modified had the following hardcoded parameters which match most existing luer locks:
    *   The luer taper starts at an inner diameter of 4.3 mm and ends with 4.0 mm and is about 6mm in length
    *   The luer taper is connected to an inner diameter of 4mm which extends another 5mm to the nozzle connection point
    *   The female luer connection starts at 5.4mm and extends to 5.6mm in diameter and is 6mm in length
    *   The female luer connection extends 5mm before it transitions into the luer taper.
    *  The female luer connection has a flange with a diameter of 7.5mm that extends outwards 1mm
    *  Two notches on the female luer connection with a size of 1x7.5x1.2 with a 5.6mm offset from the center of the part

*   **Overall:**
    *   I need the entire thing to be a single solid object, with no separate pieces. I want to be able to use the `difference()` function to make the inner channel.
    *   I'd like to use `$fn = 128` for smooth curves.
    *   I think it would be good to use colors so it's easy to visualize. I'd suggest an `orange` color for the adapter.

I think that's it, can you generate the OpenSCAD code for this? I'm not looking for any external libraries. Just a single .scad file with those parameters. Thanks!

[Assistant]
remix_luerlock.scad:
```
Inside_Radius=0.75; // [0.2:0.05:2.0]
Outside_Radius=1.25; // [1.2:0.05:2.5]
Nozzle_Length=0.0; // [0.0:50.0]

/* [Hidden] */
$fn=128;

color("orange"){

// front side
difference(){
	cylinder(r=Outside_Radius,Nozzle_Length);
	translate([0,0,-0.1]) cylinder(r=Inside_Radius,Nozzle_Length+0.2);
}

// luer connection
difference(){
	//outside
	union(){
		translate([0,0,-5]) cylinder(r1=5.4/2,r2=Outside_Radius,h=5);
		translate([0,0,-11]) cylinder(r1=5.6/2,r2=5.4/2,h=6);
		translate([0,0,-11]) cylinder(r=7.5/2,h=1);
	}
	//inside
	translate([0,0,-11.1]) cylinder(r1=4.3/2,r2=4.0/2,h=6.1);
	translate([0,0,-5.1]) cylinder(r1=4.0/2,r2=Inside_Radius,h=5.2);
	//notches
	translate([5.6/2,-7.5/2,-11.1]) cube([1,7.5,1.2]);
	translate([-5.6/2-1,-7.5/2,-11.1]) cube([1,7.5,1.2]);
}

}
```


[User]
Hey, I'm looking to create a parametric filament runout sensor enclosure for my 3D printer, specifically designed around a common microswitch used in the Tevo Tarantula kits. I have a basic design already, but I want to make it more easily customizable and robust using OpenSCAD. I'm not too confident in OpenSCAD, so I was hoping you could help generate a more flexible solution.

Here's what I'm going for, based on my original design:

*   **General Shape:** The enclosure should be a roughly rectangular box with rounded ends. It's a two-part design, so it will have two halves that screw together using M3 screws and nuts.
*   **Filament Path:** A straight hole through the enclosure for a 2.3mm diameter filament, which should have space for 4mm PTFE tubing inserts on each end. I need to be able to specify the filament diameter and PTFE tubing outer diameter as parameters.
*   **Switch Mounting:**  The microswitch needs a specific cutout, and it is mounted inside the enclosure using filament (or small screws). I'd like the parameters for switch length, height, width, padding, and diameter as well as offset (both X and Y) to be easily adjustable.
*   **Screws:**  There should be three M3 screw holes. The screw size should also be adjustable.
*   **Wall Thickness:** The walls of the enclosure should be parametrically defined, as should the overall radius for the rounded ends.
*   **Dimensions:** The length, width, and height of the entire enclosure are currently based on the included parameters, but I think it would be useful to make those adjustable to some degree too. Perhaps by controlling the length of the straight portions of the enclosure independently?
*  **Libraries:** I'd like this to use the BOSL2 library since I've seen it's great for parametric designs.

Essentially, I want a parametric OpenSCAD file (or files) that allows me to easily tweak all the relevant dimensions and parameters to fit different switches or hardware, while still maintaining the basic design. I included a copy of my original scad file, if it's helpful, but I'd much prefer a clean-slate, parametrically-driven version. I want to avoid hardcoding dimensions whenever possible.

[Assistant]
filament_runout.scad:
```
filamentDiameter = 2.3;
ptfeDiameter = 4;
screwDiameter = 3.5;
walls = 2;
radius = 3;
bottomHeight = 2;

switchLength = 13;
switchHeight = 5.8;
switchWidth = 6.5;
switchPadding = 2.5;
switchDiameter = 2.6;
switchOffsetX = 3;
switchOffsetY = 0.8;

/* [Hidden] */
$fn = 360;
filamentRadius = filamentDiameter / 2;
ptfeRadius = ptfeDiameter / 2;
screwRadius = screwDiameter / 2;
switchRadius = switchDiameter / 2;

length = (walls * 2 + switchPadding + screwDiameter) * 2 + switchLength;
width = walls * 2 + filamentDiameter + switchWidth + switchPadding;
height = switchHeight / 2 + bottomHeight;

difference() {
  hull() {
    translate([radius, -radius, 0])
      cylinder(r=radius, h=height);

    translate([length - radius, -radius, 0])
      cylinder(r=radius, h=height);

    translate([length - radius, radius - width, 0])
      cylinder(r=radius, h=height);

    translate([radius, radius - width, 0])
      cylinder(r=radius, h=height);

    translate([length / 2, -width + walls - radius, 0])
      cylinder(r=radius + walls / 2, h=height);
  }

  // Switch cutout
  group() {
    translate([walls * 2 + screwDiameter + switchPadding, -switchWidth, bottomHeight])
      cube([switchLength, switchWidth + 1, height]);

    translate([walls * 2 + screwDiameter, -width + walls, bottomHeight])
      cube([switchLength + switchPadding * 2, width - walls * 2, height]);
  }

  // Filament
  translate([-1, -width + walls + screwDiameter + filamentRadius - 0.8, height])
    rotate([0, 90, 0])
      cylinder(r=filamentRadius, h= length + 2);

  // PTFE tube holes
  group() {
    translate([-1, -width + walls + screwDiameter + filamentRadius - 0.8, height])
      rotate([0, 90, 0])
        cylinder(r=ptfeRadius, h= walls + radius + 1);

    translate([length - walls - radius, -width + walls + screwDiameter + filamentRadius - 0.8, height])
      rotate([0, 90, 0])
        cylinder(r=ptfeRadius, h= walls + radius + 1);
  }

  // Screwholes
  group() {
    translate([screwRadius + walls, -screwRadius - walls, -1])
      cylinder(r=screwRadius, h=height + 2);

    translate([length - walls - screwRadius, -screwRadius - walls, -1])
      cylinder(r=screwRadius, h=height + 2);

    translate([length / 2, -width + walls - radius, -1])
      cylinder(r=screwRadius, h=height + 2);
  }

  // Switch Holes
  group() {
    translate([walls * 2 + screwDiameter + switchPadding + switchOffsetX, -switchRadius - switchOffsetY, -1])
      cylinder(r=switchRadius, h=height);

    translate([walls * 2 + screwDiameter + switchPadding + switchLength - switchOffsetX, -switchRadius - switchOffsetY, -1])
      cylinder(r=switchRadius, h=height);

  }
}

```


[User]
I want to create a customizable 2D origami-style corgi design that I can 3D print. I've seen a few examples online, and they look pretty cool. I need the design to be parametric so I can control its size and line thicknesses.

Here's what I'm thinking:

1.  **Overall Shape:** The corgi will be a 2D shape derived from a set of outline points. The attached SCAD file (customizable_origami_corgi.scad) has these points in it. It also has inner points and polygons for cutting out inner sections. I want to be able to specify the maximum size of the longest side, and the design should automatically scale the other dimension to maintain the aspect ratio. Also, I need to control the overall height/thickness of the printed model.

2.  **Outline:** The outer outline should have a user-defined thickness. The inner cutouts also need a line thickness which I'd also like to be customizable and set to a value, ideally smaller than the outer outline thickness. Finally, the inside edges of the inner cutouts should have a customizable radius for rounding them off, again by a user-set value.

3. **Mirroring/Rotation:** I would like to be able to flip the design horizontally before creating the final output. I need that as a parameter, as well.

4.  **OpenSCAD:** I'd like this in OpenSCAD, and I don't want to use external libraries, so just vanilla OpenSCAD would be best.

So, in summary, I need a parametric OpenSCAD file that creates a 2D corgi with adjustable size, outline thicknesses, inner outline roundness, and the option to mirror the design. Can you help me with that?

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

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

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

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

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

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

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

// Roundiness of the ends of the inner outlines.
inline_edge_radius_in_millimeter = 0.5; //[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 = [18, 582];
A2 = [16, 522];
A3 = [170, 468];
A4 = [521, 491];
A5 = [883, 476];
A6 = [1136, 22];
A7 = [1234, 171];
A8 = [1328, 197];
A9 = [1381, 254];
A10 = [1565, 295];
A11 = [1540, 365];
A12 = [1404, 450];
A13 = [1311, 484];
A14 = [1346, 560];
A15 = [1334, 734];
A16 = [1270, 798];
A17 = [1152, 928];
A18 = [1149, 1004];
A19 = [1107, 1071];
A20 = [1183, 1138];
A21 = [1059, 1138];
A22 = [1006, 1076];
A23 = [968, 932];
A24 = [492, 906];
A25 = [317, 1070];
A26 = [394, 1138];
A27 = [253, 1138];
A28 = [122, 836];
A29 = [86, 622];

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

// Inner Points
B1 = [885, 583];
B2 = [1138, 489];
B3 = [1068, 320];

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

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

min_x = A2[0];
min_y = A6[1];
max_x = A10[0];
max_y = A21[1];

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

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

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

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

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

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

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

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

```


[User]
I'm looking to create a customizable origami polar bear design in OpenSCAD. The design is based on a series of 2D points that define the outer shape and inner cut-outs of the bear. I need a parametric design where I can control the overall size, height, and thicknesses of the outer and inner outlines.

Specifically, I'd like to be able to:

1.  Set the maximum size of the longest side of the bear. The shorter side should automatically resize to maintain the aspect ratio.
2.  Set the overall height (thickness) of the model.
3.  Set the thickness of the outer outline.
4.  Set the thickness of the inner outlines (cuts).
5.  Set the roundness radius for the ends of the inner outlines.
6.  Flip the model horizontally as an option.

The design will use several sets of points for the outer outline and several polygons for the inner cut-outs. The point coordinates and polygon definitions are already provided and should be used directly in the code. I need the code to scale these points appropriately, create the 2D shape with outlines and cuts, and then extrude it to the desired height. I'd like to make sure the parameters are easily adjustable through the OpenSCAD customizer. Please use a `$fn=32` to ensure smooth curves. I don't need any libraries besides standard OpenSCAD operations.

[Assistant]
customizable_origami_polar_bear.scad:
```
/*
 * Customizable Origami - Polar Bear - https://www.thingiverse.com/thing:
 * by Dennis Hofmann - https://www.thingiverse.com/mightynozzle/about
 * created 2017-11-24
 * 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 = 2.2; //[0.5:0.1:20]

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

// Roundiness of the ends of the inner outlines.
inline_edge_radius_in_millimeter = 0.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 = [176, 905];
A2 = [215, 860];
A3 = [164, 674];
A4 = [223, 497];
A5 = [290, 393];
A6 = [426, 208];
A7 = [460, 165];
A8 = [454, 115];
A9 = [497, 117];
A10 = [595, 121];
A11 = [673, 209];
A12 = [661, 224];
A13 = [692, 271];
A14 = [721, 311];
A15 = [680, 330];
A16 = [657, 338];
A17 = [588, 311];
A18 = [572, 330];
A19 = [625, 470];
A20 = [683, 522];
A21 = [725, 553];
A22 = [705, 598];
A23 = [683, 588];
A24 = [660, 585];
A25 = [653, 779];
A26 = [741, 845];
A27 = [787, 829];
A28 = [789, 882];
A29 = [786, 931];
A30 = [519, 931];
A31 = [242, 931];

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

// Inner Points
B1 = [447, 703];
B2 = [431, 515];
B3 = [546, 424];
B4 = [495, 312];
B5 = [503, 544];

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

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

min_x = A3[0];
min_y = A8[1];
max_x = A28[0];
max_y = A29[1];

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

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

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

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

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

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

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

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

```


[User]
Hey, I'm looking to create a set of stackers for my IKEA Lack tables, and I'd like to do it with OpenSCAD. I've got a basic idea, but I'm not an expert and need a little help getting started with the code.

Basically, I want a design that allows me to stack Lack tables without damaging them by using screws or anything. The idea is to create a kind of 'clamp' that fits around the table leg, grabbing onto the threaded part that usually screws into the table top. The design should sit between the leg and the table surface, providing a stable connection.

The design needs to be parametric so that I can adjust it easily to fit various configurations. Specifically, I'd like to be able to modify:
*   **Wall Thickness:** Both the vertical and horizontal walls of the 'clamp' need to be adjustable. I'd need a parameter for the vertical wall thickness and a parameter for the horizontal.
*   **Lack Leg Width:** This should be a parameter since IKEA can change things and I may need to adjust for slightly different tables. It will also affect the internal size of the clamp.
*   **Lack Table Surface Height:** I also want to parameterize the height of the table surface, since that also affects the design height.
*   **Spacer Height:** This parameter would allow me to add extra vertical space between the stacked tables, as needed to fit things in between like a 3D printer. I’d like to have the option to make this zero.
*   **Screw Radius:**  The hole for the threaded rod in the leg should also be a parameter, to account for tolerances and make it easy to adjust for a snug fit.

I'd like a main module that pieces all the parts together. It would consist of:
*   A base to rest the bottom of the table's legs on. This will have a hole for the threaded rod.
*   A section that wraps around the table leg.
*   A top section that includes the 'mount' that the table will rest on. This section also needs to support the next table on top.

The design should be reasonably sturdy, so maybe you can incorporate some rotation in the support section to help with that. And it should be able to stack up in multiple configurations (like with the table upside down, I guess). The top part will probably be the most challenging as it needs to wrap around the table's leg, support the tabletop, and also contain the mount for the next leg to fit onto.

I think that's everything. Let me know if you have any questions, I can try to clarify!

[Assistant]
lack_stacker-v6.1.scad:
```
$fn = 100;

// Tolerance to use for the different measurements to accomodate filament thickness.
tolerance = 1;

// Thickness of the vertical walls in the model.
wall_w = 5;
// Thickness of the horizontal walls in the model.
wall_h = 5;

// The width (in mm) of the LACK table's square leg.
lack_leg_width = 51;
leg_width = lack_leg_width + 2 * tolerance;

// The height (in mm) of the LACK table's surface.
lack_surface_height = 50;
surface_height = lack_surface_height + tolerance;

// The extra space (in mm) to add to the top LACK's leg to ensure large objects (like a 3D printer) fit between the stacked tables.
spacer_height = 60;

// The radius (in mm) of the hole that should fit the threaded pole of the LACK table's leg. Make the hole somewhat bigger to ensure it definitely fits inside.
lack_screw_radius = 5;
screw_radius = lack_screw_radius + tolerance;

module floor_area() {
    translate([wall_w, 0, 0]) {
        cube([leg_width, leg_width, wall_h]);
    }
}

module top_area() {
    translate([-wall_w, 0, 0]) {
        cube([leg_width + 2 * wall_w, leg_width + 2 * wall_w, spacer_height + wall_h]);
    }
}

module wall() {
    cube([wall_w, leg_width + wall_w, surface_height + wall_h]);
}

module bottom_wall() {
    union() {
        wall();
        rotate([5, 0, 0]) {
            translate([0, 0, 0.5]) {
                wall();
            }
        }
    }
}

module top_wall() {
    translate([-wall_w, wall_w, -surface_height / 2]) {
        difference(){
            difference(){
                wall();
                translate([0, 0, wall_h]) {
                    rotate([45, 0, 0]) {
                        translate([-wall_w, 0, 0]){
                            cube([wall_w*3, leg_width * 2, surface_height + wall_h]);
                        }
                    }
                }
            }
            cube([2 * wall_w, leg_width * 2, surface_height / 2]);
        }
    }
}

module screw_hole () {
    translate([(leg_width / 2) + wall_w, (leg_width) / 2, wall_h / 2]) {
        cylinder(r = screw_radius, h = wall_h + 1, center = true);
    }
}

// The bottom part
difference() {
    floor_area();
    screw_hole();
}

// The part that wraps around the table
bottom_wall();
rotate(-90) {
    translate([-(leg_width), (leg_width + wall_w), 0]) {
        rotate([180, 180, 0]) bottom_wall();
    }
}

// The top part that includes the mount up
rotate(180) {
    translate([-(leg_width + wall_w), -(leg_width + wall_w), surface_height + wall_h]) {
        top_area();
        translate([0, 0, spacer_height]) {
            top_wall();
            rotate(-90)
            translate([-(leg_width + wall_w), (leg_width + wall_w), 0]) {
                mirror([0, 1, 0]) {
                    top_wall();
                }
            }
        }
    }
}

```


[User]
I'd like to create a customizable origami snail design using OpenSCAD, similar to the one described in the Thingiverse link. I need a script that allows me to adjust the overall size, height, and the thicknesses of the inner and outer outlines.

Specifically, I need these parameters to be adjustable:

*   **`max_size_in_millimeter`**: The maximum length of the longest side of the design. The shorter side should scale proportionally.
*   **`model_height_in_millimeter`**: The overall height of the model.
*   **`outline_size_in_millimeter`**: The thickness of the outer outline.
*  **`inline_size_in_millimeter`**: The thickness of the inner outline.
*   **`inline_edge_radius_in_millimeter`**:  The radius used to round the edges of the inner outlines.
*   **`flip_model`**: An option to flip the model along the horizontal axis, with the options of "yes" or "no".

The script should use the provided 2D point data for the snail's outline and inner cuts. Here are the outer points (`A1`-`A20`) and inner points (`B1`-`B27`), and the polygons (`C1`-`C7`) they form (copying these from the provided SCAD):

```
// Outer Points
A1 = [345, 760];
A2 = [697, 983];
A3 = [763, 917];
A4 = [605, 759];
A5 = [604, 446];
A6 = [919, 126];
A7 = [1234, 126];
A8 = [1550, 448];
A9 = [1553, 759];
A10 = [1396, 925];
A11 = [1758, 1083];
A12 = [1235, 1083];
A13 = [898, 1083];
A14 = [604, 1083];
A15 = [275, 777];
A16 = [284, 445];
A17 = [122, 286];
A18 = [303, 420];
A19 = [441, 286];
A20 = [326, 444];

// Inner Points
B1 = [1076, 925];
B2 = [916, 768];
B3 = [918, 448];
B4 = [1070, 291];
B5 = [1234, 290];
B6 = [1390, 447];
B7 = [1383, 604];
B8 = [1232, 754];
B9 = [1079, 606];
B10 = [1139, 507];
B11 = [1232, 509];
B12 = [1284, 589];
B13 = [1280, 600];
B14 = [1225, 519];
B15 = [1142, 520];
B16 = [1093, 604];
B17 = [1228, 737];
B18 = [1366, 599];
B19 = [1370, 451];
B20 = [1227, 311];
B21 = [1081, 316];
B22 = [947, 447];
B23 = [942, 758];
B24 = [1085, 888];
B25 = [1391, 889];
B26 = [1115, 726];
B27 = [1123, 714];

// Polygons
C1 = [A17, A16, A18];
C2 = [A16, A18, A19, A20];
C3 = [A16, A15, A1, A20];
C4 = [A15, A14, A2, A1];
C5 = [A14, A13, A3, A2];
C6 = [A12, A10, A11];
C7 = [B13, B14, B15, B16, B27, B17, B18, B19, B20, B21, B22, B23, B24, B25, A9, A8, A7, A6, A5, A4, A3, A13, A12, A10, B1, B2, B3, B4, B5, B6, B7, B8, B26, B9, B10, B11, B12];
```

The script should use linear extrusion to create the 3D model, and use `offset()` to generate the inner and outer lines/cuts, and `difference()` to do the cutting. The code should also ensure proper scaling of the design based on `max_size_in_millimeter` to maintain the aspect ratio of the original design. Let me know if you have any questions!

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

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

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

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

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

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

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

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

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

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

// Outer Points
A1 = [345, 760];
A2 = [697, 983];
A3 = [763, 917];
A4 = [605, 759];
A5 = [604, 446];
A6 = [919, 126];
A7 = [1234, 126];
A8 = [1550, 448];
A9 = [1553, 759];
A10 = [1396, 925];
A11 = [1758, 1083];
A12 = [1235, 1083];
A13 = [898, 1083];
A14 = [604, 1083];
A15 = [275, 777];
A16 = [284, 445];
A17 = [122, 286];
A18 = [303, 420];
A19 = [441, 286];
A20 = [326, 444];

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

// Inner Points
B1 = [1076, 925];
B2 = [916, 768];
B3 = [918, 448];
B4 = [1070, 291];
B5 = [1234, 290];
B6 = [1390, 447];
B7 = [1383, 604];
B8 = [1232, 754];
B9 = [1079, 606];
B10 = [1139, 507];
B11 = [1232, 509];
B12 = [1284, 589];
B13 = [1280, 600];
B14 = [1225, 519];
B15 = [1142, 520];
B16 = [1093, 604];
B17 = [1228, 737];
B18 = [1366, 599];
B19 = [1370, 451];
B20 = [1227, 311];
B21 = [1081, 316];
B22 = [947, 447];
B23 = [942, 758];
B24 = [1085, 888];
B25 = [1391, 889];
B26 = [1115, 726];
B27 = [1123, 714];

// Polygons
C1 = [A17, A16, A18];
C2 = [A16, A18, A19, A20];
C3 = [A16, A15, A1, A20];
C4 = [A15, A14, A2, A1];
C5 = [A14, A13, A3, A2];
C6 = [A12, A10, A11];
C7 = [B13, B14, B15, B16, B27, B17, B18, B19, B20, B21, B22, B23, B24, B25, A9, A8, A7, A6, A5, A4, A3, A13, A12, A10, B1, B2, B3, B4, B5, B6, B7, B8, B26, B9, B10, B11, B12];

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

min_x = A17[0];
min_y = A6[1];
max_x = A11[0];
max_y = A11[1];

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

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

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

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

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

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

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

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

```


[User]
I'd like to create a customizable 2D origami pig design, similar to the one described in the provided Thingiverse link. I need an OpenSCAD file that allows me to control several parameters:

1.  **Overall Size:** I want to be able to set a maximum size for the longest side of the pig. The shorter side should then scale proportionally.
2.  **Height:** The pig should be a flat design, but I need to control the height (thickness) of the extrusion.
3.  **Outline Thicknesses:** I want separate control over the thickness of the outer outline and the inner "cut" lines that define the origami folds.
4.  **Inner Outline Roundness:** I'd like to be able to control the radius of the rounded edges on the inner outlines to give it a smoother look.
5. **Mirroring:** I need the option to flip the model across its horizontal axis.

The provided code uses a series of points to define both the outer shape and inner cut paths. I'd like the new code to be structured similarly, perhaps using a module that generates the pig. I don't need any libraries at this point since everything should be done with the basic OpenSCAD built-in functions. I just need the `customizable_origami_pig.scad` file that will use these points and the customization parameters above.

Please make the code easy to read and understand, with comments that describe the different parts of the design process. I don't need any complex calculations or advanced functions that are not readily available in default OpenSCAD.

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

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

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

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

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

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

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

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

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

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

// Outer Points
A1 = [301, 984];
A2 = [427, 903];
A3 = [424, 872];
A4 = [677, 678];
A5 = [1134, 657];
A6 = [1392, 654];
A7 = [1479, 768];
A8 = [1571, 919];
A9 = [1676, 922];
A10 = [1697, 1055];
A11 = [1629, 1091];
A12 = [1350, 1273];
A13 = [1395, 1408];
A14 = [1242, 1276];
A15 = [782, 1284];
A16 = [520, 1408];
A17 = [532, 1301];
A18 = [429, 1344];
A19 = [456, 1034];

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

// Inner Points
B1 = [559, 972];
B2 = [546, 1212];
B3 = [1076, 1023];
B4 = [1316, 936];
B5 = [1258, 965];
B6 = [1332, 1226];

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

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

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

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

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

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

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

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

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

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

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

```


[User]
Hey, I'm looking to create a customizable door hook in OpenSCAD, and I'd like your help designing the code. It should be based on a design I already have, but I'd like to be able to tweak all the dimensions easily.

Here's the basic idea: the hook is made of a couple of rectangular pieces, sort of a sideways "L", with a cylindrical hook hanging down, and a wedge to keep it on the door. There are also a couple of small cylinder bumps for extra grip when it's closed.

Here are the parameters I need to control:

*   `a`: The inner width of the main part of the hook. This is the distance between the two main vertical pieces where the door sits, and should have a little bit of wiggle room as well.
*   `b`: The length of the shorter arm of the L-shape.
*   `height`: The height/thickness of all the main pieces, and most of the cylinders.
*   `a_thickness`: The thickness of the main rectangular piece (the one sitting horizontally on the top of the door)
*   `b_thickness`: The thickness of the rectangular pieces that go over the sides of the door.
*   `bump`: The diameter of the small bumps that are on the main pieces (the little cylinders), and they should extrude *out* of the main structure.
*   `c`: The vertical distance the hook hangs down from the main horizontal rectangle
*   `d`: The diameter of the main part of the cylindrical hook at the very end, where it bulges out.
*   `e`: The diameter of the cylinder neck of the hook, above the bulging part.
*   `angle`: The angle of the wedge used to secure the hook on the door.

I'd like to have all the major dimensions be configurable. The code should not use any libraries other than OpenSCAD's default modules, though. Could you create a parameterized OpenSCAD file for this?

[Assistant]
doorhook.scad:
```
a = 32;
b = 40;
height = 20;
a_thickness = 1;
b_thickness = 2.5;
bump = 2;
c = 50;
d = 20;
e = 15;

cube ([a+2*b_thickness, a_thickness, height]);

translate([a+b_thickness,0,0])
rotate (-90)
cube ([b, b_thickness, height]);

rotate (-90)
cube ([c, b_thickness, height]);

difference(){
translate ([-e/2,-c+0.000001,0])
scale ([1, (d+2*b_thickness)/(e+2*b_thickness),1])
difference(){
    cylinder (d=e+2*b_thickness, h = height);
    rotate(90)
    translate([0,0,-0.1*height])
    cube([d+3*b_thickness, d+3*b_thickness, 3*height]);
}

translate ([-e/2,-c + d/2,0])
cube ([e, d, 3*height], center = true);

translate ([-e/2,-c,0])
scale ([1, d/e,1])
cylinder (d=e, h = 3*height, center = true);
}

angle = 40;

translate([-e,-c,0])
rotate([0,-90,0])
linear_extrude(height = b_thickness){
polygon([[0,0],[height,0],[height/2,1/tan(angle)*height/2]]);
}

translate([b_thickness/2,a_thickness,0])
scale([1,bump/b_thickness,1])
cylinder (d = b_thickness, h = height, $fn = 20);

translate([b_thickness*1.5+a,a_thickness,0])
scale([1,bump/b_thickness,1])
cylinder (d = b_thickness, h = height, $fn = 20);
```


[User]
Okay, I'm looking to design a cycloidal drive gearbox, and I'd like to use OpenSCAD to generate the parts. I'd like it to be fully parametric, allowing me to easily adjust dimensions and ratios. I've seen a few designs out there, but I want one that's flexible enough for my needs. Here's what I'm thinking:

**Overall Structure:**

The design will consist of several main components: an outer ring or housing, a drive disc (or driven disc), a rotor, and a motor shaft. I need to be able to generate each of these parts separately for printing and assembly.

**Key Parameters:**

*   **`quality`**:  This will control the number of segments used for curved surfaces and will be directly tied to `$fn`. A higher value should result in smoother curves. The range should be something like 10 to 100.
*   **`speed_ratio`**: The reduction ratio of the drive, such as 10:1, 20:1 etc., should be an integer and a range from 3 to 50 seems good.
*   **`gearbox_height`**: The total height of the assembled gearbox, excluding the motor shaft. Range should be 5 to 50, with steps of 0.5.
*   **`gearbox_diameter`**:  The overall diameter of the gearbox. A good range would be 10 to 200, with steps of 1.
*   **`SHOW_PART`**: This parameter will be used to display a specific part of the model, or all of the parts together. I'd need a selection like "All", "drive disc", "outer ring", "Rotor", "Shaft".
*   **`CLEARANCE_INPLACE`**: The clearance between parts that fit together when they're not moving, something small, maybe 0 to 1.
*   **`CLEARANCE_MOVE`**: The clearance between moving parts, also 0 to 1.
*   **`CLEARANCE_MOVE_BRIDGING`**: Clearance used where bridging may be required. 0 to 1 as well.
*   **`CLEARANCE_FIT`**: General fit tolerance between non moving parts, also from 0 to 1.
*   **`layer_resolution`**: Height of each printed layer, something like 0.05 to 0.4.
*   **`outside_perimeter_width`**: The thickness of the outer wall of the gearbox. I'd like to be able to set negative values to experiment, so something like -5 to 6 in 0.1 steps.
*   **`drive_shaft_diameter`**: The diameter of the motor shaft. Range of 1 to 20 and steps of 0.1 should be good.
*   **`drive_shaft_diameter_hollow`**: The diameter of the hollow part of the motor shaft. The range should be the same as drive shaft diameter, and go up to and including the `drive_shaft_diameter`.
*   **`drive_shaft_sides`**:  Number of sides of the motor shaft, for splined shafts, a value of 0 should result in a cylinder. The range should go from 3 to 200.
*   **`drive_shaft_sides_hollow`**: Similar to the above, but for the hollow part of the motor shaft.
*  **`drive_shaft_length`**: The length of the motor shaft portion, range of 0 to 50
*   **`number_rotor_holes`**: The number of holes in the rotor. Range 2 to 20 seems sensible.
*   **`driven_disc_height`**: The height of the drive disc. Maybe 0.5 to 8 with steps of 0.25
*   **`driven_disc_shaft_diameter`**: The diameter of the shaft hole in the driven disc, range of 0.5 to 25
*   **`driven_disc_shaft_sides`**: The number of sides for the driven disc shaft hole, similar to the motor shaft.
*   **`top_thickness`**: Thickness of the top plate of the gearbox, something like 1 to 5
*   **`top_struts`**: Number of supporting struts in the top of the gearbox, range of 2 to 10.
*   **`top_strut_width`**: The width of supporting struts, range of 1 to 5.
*    **`top_wall_thickness_contstraining_driven_disc`**: The thickness of the top plate wall that constrains the driven disc, range of 0.5 to 2.
*  **`chamfer`**: The chamfer amount used on the drive shaft and motor hole, range of 0 to 1.
*   **`conf_rotor_segments`**: Number of segments the rotor is split into, 0 for auto calculation, MUST be printed seperately. Range of 0 to 100.
*  **`twisted_tooth_interpolation_enabled`**: Allows for twisting of the rotor segment teeth, a boolean of 0 or 1.

**Key Design Features:**

*   **Cycloidal Profile:** The rotor should have a true cycloidal profile based on the selected speed ratio.
*   **Rotor Segments:** The rotor should be able to be split into segments to allow for printing without supports. The amount of segmentation should be a parameter, and optionally calculated based on the layer resolution.
*   **Motor Shaft:** The motor shaft should be chamfered, to print without supports. The shaft needs to be able to be created with different number of sides for splined shafts.
*   **Clearances:** Clearances should be carefully managed to allow for smooth rotation of components without excessive slop, using the parameters defined above.
*   **Holes:** There should be a number of holes in the rotor, spaced evenly. Their size should be calculated automatically, based on the other parameters. They should be large enough to accommodate the "drive pins" on the driven disk.
*   **Drive pins:** The "drive pins" should be on the driven disk, to fit into the rotor holes. Their size should be calculated based on the size of the rotor holes with the clearance. They need to have a small clearance with the rotor holes to allow for movement.
*   **Driven Disc Shaft:** The driven disc needs to have a central shaft hole to attach it to an output, or to a bearing.
*   **Outer Ring:** The outer ring or housing should have a suitable shape to constrain the moving parts of the gearbox.

**Outputs:**

I'd like to be able to output each of the following parts as separate STL files:

1.  Outer ring
2.  Drive disc (driven disc)
3.  Rotor
4.  Motor shaft

I'd also like an option to generate a combined view of all parts for visualization purposes.

Could you please create the OpenSCAD code for this? I'm not particular about which libraries to use if any, as long as it gets the job done. I'm expecting you to generate the entire design, not build on existing files.

[Assistant]
cycloid_drive.scad:
```
/* [Main] */
// overall quality -> higher values produce smoother surface, but will increase rendering time and file size considerably
quality=100; // [10:10:100]

// the desired speed ratio x:1
speed_ratio=10; // [3:1:50]

// height of the gearbox (without motor shaft)
gearbox_height=10; // [5:0.5:50]
// diameter of the gearbox
gearbox_diameter=50; // [10:1:200]

// which part to show, use one at a time to create printable parts
SHOW_PART=0; // [0:All,2:drive disc,3:outer ring,4:Rotor,5:Shaft]

/* [Advanced] */
CLEARANCE_INPLACE=0.2; // [0:0.025:1]
CLEARANCE_MOVE=0.175; // [0:0.025:1]
CLEARANCE_MOVE_BRIDGING=0.4; // [0:0.025:1]
CLEARANCE_FIT=0.1; // [0:0.025:1]
layer_resolution=0.25; // [0.05:0.05:0.4]
outside_perimeter_width=1; // [-5:0.1:6]
drive_shaft_diameter=9; // [1:0.1:20]
drive_shaft_diameter_hollow=7; // [0:0.1:20]
// 0 = circle
drive_shaft_sides=200; // [3:1:200]
// 0 = circle
drive_shaft_sides_hollow=6; // [3:1:200]
drive_shaft_length=18; // [0:0.5:50]
number_rotor_holes=7; // [2:1:20]
driven_disc_height=1; // [0.5:0.25:8]
driven_disc_shaft_diameter=13; // [0.5:0.25:25]
driven_disc_shaft_sides=6; // [3:1:200]
top_thickness=1;
top_struts=5;
top_strut_width=3.6;
top_wall_thickness_contstraining_driven_disc=0.96;
chamfer=0.6;

/* [Experimental] */
// number of disc segments - use >= 2 for vibration cancelling; 0 = automatic; MUST be printed seperately
conf_rotor_segments=1; // [0:1:100]
twisted_tooth_interpolation_enabled=0; // [1:Yes,0:No]

/* [Hidden] */
PI=3.141592;
OVERLAP=0.01;
$fn=quality;
tooth_diameter=(gearbox_diameter-2*outside_perimeter_width-2*clearance_outline_to_rotor())/(2*(speed_ratio+2));
tooth_radius=tooth_diameter/2;
eccentric_offset=2*tooth_diameter;
eccentric_cylinder_diameter=drive_shaft_diameter+eccentric_offset;
rotor_height=rotor_height();

nozzle_diameter = 0.48;
max_overhang = max_overhang();
rotor_diameter = rotor_diameter();
rotor_diameter_inner=rotor_diameter-4*tooth_diameter-OVERLAP;
rotor_segments = num_rotor_segments();

driven_disc_diameter=gearbox_diameter-2*outside_perimeter_width-2*CLEARANCE_MOVE;
drive_pin_wall_thickness=2*nozzle_diameter+0.1;

available_space_for_rotor_holes = rotor_diameter/2-1*tooth_diameter-drive_shaft_diameter/2-eccentric_offset-chamfer/2-clearance_outline_to_rotor();
rotor_hole_wall_thickness=2*nozzle_diameter;

rotor_hole_diameter = tooth_diameter*4;
drive_pin_diameter_nominal = rotor_hole_diameter/2;

degrees_tooth_outer = 360/(speed_ratio+1);
degrees_tooth_inner = 360/speed_ratio;

xOffset=available_space_for_rotor_holes/2+drive_shaft_diameter/2+eccentric_offset/2+chamfer+clearance_shaft_to_rotor();

rotate = $t*360*speed_ratio;

if(showpart(0)){
//translate([-gearbox_diameter-2,0,0])
color([1,0,0,0.99])
rotate([180,0,0])
translate([0,0,-gearbox_height+driven_disc_height+top_thickness])
//outer_perimeter_with_tooth();
outer_perimeter();
}

if(showpart(4)){
rotors_V2(rotor_segments);
}

if(showpart(5) || showpart(4)){
rotate([0,0,-$t*360*speed_ratio])
color([0,1,0])
eccentric_with_motor_shaft();
}

if(showpart(2)){
color([0,0,1])
//translate([gearbox_diameter+1,0,0])
translate([0,0,-2])
rotate([0,0,$t*360])
    driven_disc();
}

if(SHOW_PART == 3){
color([1,0,0,1])
    outer_perimeter();
    //top_cover_legacy();
}

module cyclogearprofile(rtooth,nteeth,quality,hollow=false){
  function hypo_cyclo(r1,r2,phi) =
   [(r1-r2)*cos(phi)+r2*cos(r1/r2*phi-phi),(r1-r2)*sin(phi)+r2*sin(-(r1/r2*phi-phi))];
  function epi_cyclo(r1,r2,phi) =
   [(r1+r2)*cos(phi)-r2*cos(r1/r2*phi+phi),(r1+r2)*sin(phi)-r2*sin(r1/r2*phi+phi)];
  // alternating hypo- and epicycloids
  function epihypo(r1,r2,phi) =
    pow(-1, 1+floor( (phi/360*(r1/r2)) )) <0 ? epi_cyclo(r1,r2,phi) : hypo_cyclo(r1,r2,phi);

  rrollcircle = rtooth*(2*nteeth);
  npoints = nteeth*quality;

  list1ToN  = [ for (i = [0 : npoints]) i ];
  pointlist = [ for (i = list1ToN) epihypo(rrollcircle,rtooth,360/npoints*i) ];
      difference(){
  polygon(points = pointlist, paths = [list1ToN],convexity = 6);
          if(hollow){
            circle(d=rotor_diameter_inner);
          }
      }
}

module rotors(segments){
    height = rotor_height/segments;
    degrees_per_segment = 360/segments;
    for (i = [0:segments-1]){
        degrees=i*degrees_per_segment;
        tooth_overlap = degrees/360;
        tooth_rotate_to_avoid_overlap=degrees_tooth_inner*tooth_overlap;

        translate([-cos(rotate+degrees)*eccentric_offset/2,sin(rotate+degrees)*eccentric_offset/2,0])
rotate([0,0,$t*360])
        translate([0,0,i*height])
        linear_extrude(height,twist=twisted_tooth_interpolation_enabled*degrees_per_segment/speed_ratio)
            rotor_2d(degrees,tooth_rotate_to_avoid_overlap);
    }
}

module rotors_V2(segments){
    height = rotor_height/segments;
    degrees_per_segment = 360/segments;
    for (i = [0:segments-1]){
        degrees=i*degrees_per_segment;
        tooth_overlap = degrees/360;
        tooth_rotate_to_avoid_overlap=degrees_tooth_inner*tooth_overlap;

        translate([-cos(rotate+degrees)*eccentric_offset/2,sin(rotate+degrees)*eccentric_offset/2,0])
        rotate([0,0,$t*360])
        translate([0,0,i*height])
        linear_extrude(height,twist=twisted_tooth_interpolation_enabled*degrees_per_segment/speed_ratio)
            rotor_2d(degrees,tooth_rotate_to_avoid_overlap,true);

        translate([-cos(rotate+degrees)*eccentric_offset/2,sin(rotate+degrees)*eccentric_offset/2,0])
        translate([0,0,i*height])
        {
            rotate([0,0,$t*360])
            difference(){
                cylinder(d=rotor_diameter_inner,h=height);

                cylinder(d=eccentric_cylinder_diameter+2*clearance_shaft_to_rotor());
                for(i=[0:number_rotor_holes-1]){
                    rotate([0,0,i*360/number_rotor_holes])
                    translate([xOffset,0,-OVERLAP/2])
                    cylinder(d=rotor_hole_diameter,h=height+OVERLAP);
                }
                dia=drive_shaft_diameter+eccentric_offset+2*CLEARANCE_MOVE;
                translate([0,0,-OVERLAP/2])
                chamfered_bi_cylinders(dia,chamfer,height+OVERLAP);
            }
        }
    }
}
module rotor_2d(degrees,rotate_degrees,hollow){
    difference(){
        rotate([0,0,rotate_degrees])
        cyclogearprofile(tooth_radius,speed_ratio,quality,hollow);
        circle(d=eccentric_cylinder_diameter+2*clearance_shaft_to_rotor());
        for(i=[0:number_rotor_holes-1]){
            rotate([0,0,i*360/number_rotor_holes])
            translate([xOffset,0,0])
            circle(d=rotor_hole_diameter);
        }
    }
}

module outer_perimeter_with_tooth(height=rotor_height){
    linear_extrude(height)
    rotate([0,0,degrees_tooth_outer/2])
    difference()
        {
            circle(d=gearbox_diameter);
            cyclogearprofile(tooth_radius,speed_ratio+1,quality);
          offset(delta = clearance_outline_to_rotor())
            cyclogearprofile(tooth_radius,speed_ratio+1,quality);
        }
}

module eccentric_with_motor_shaft(){
    difference(){
        union(){
            motor_shaft(drive_shaft_diameter,drive_shaft_sides);

            eccentric(rotor_height, eccentric_offset, eccentric_cylinder_diameter);
        }
        translate([0,0,-OVERLAP/2])
            motor_shaft(drive_shaft_diameter_hollow,drive_shaft_sides_hollow,OVERLAP);
    }
}

module motor_shaft(diameter,side_count_indication,height_offset=0){
    cylinder(d = diameter, h = rotor_height+drive_shaft_length+height_offset, $fn=circle_sides(side_count_indication));
}

module eccentric(discs_thickness, eccentric_offset, rotor_gear_outer_radius){
    degrees_per_segment = 360/rotor_segments;
    height_per_segment = discs_thickness/rotor_segments;
    for (i=[0:rotor_segments-1]){
        translate([-cos(i*degrees_per_segment)*eccentric_offset/2, sin(i*degrees_per_segment)*eccentric_offset/2, i*height_per_segment])
            //cylinder(d = rotor_gear_outer_radius, h = height_per_segment);
        chamfered_bi_cylinders(rotor_gear_outer_radius,chamfer,height_per_segment);
    }
}

module chamfered_bi_cylinders(dia,chamfer,height){
    overlap_height = height + OVERLAP;
    cylinder(d1=dia+chamfer,d2=dia,h=overlap_height/2);
    translate([0,0,overlap_height/2-OVERLAP/2])
    cylinder(d1=dia,d2=dia+2*chamfer,h=overlap_height/2);
}

module driven_disc(){
    difference(){
        cylinder(d=driven_disc_diameter,h=driven_disc_height);

        translate([0,0,-OVERLAP/2])
        cylinder(d=driven_disc_shaft_diameter,h=driven_disc_height+OVERLAP,$fn=circle_sides(driven_disc_shaft_sides));
    }
    for(i=[0:number_rotor_holes]){
        translate([-eccentric_offset/2+rotor_hole_diameter/2-drive_pin_diameter_nominal/2,0,driven_disc_height])
            rotate([0,0,i*360/number_rotor_holes])
            translate([xOffset,0,0])
            difference(){
                cylinder(d=drive_pin_diameter_nominal-2*CLEARANCE_MOVE,h=rotor_height);

                cylinder(d=drive_pin_diameter_nominal-2*drive_pin_wall_thickness,h=rotor_height);
                // fixes rendering preview issue:
                translate([0,0,rotor_height-OVERLAP/2])

                cylinder(d=drive_pin_diameter_nominal-2*drive_pin_wall_thickness-2*CLEARANCE_MOVE,h=OVERLAP);
            }
        }
}

module outer_perimeter(){
    xxx = rotor_diameter-3*tooth_diameter;

    union(){
        union(){
            rotate([0,0,degrees_tooth_outer/2]) // to allign artefacts with outer_perimeter_with_tooth()
            translate([0,0,-top_thickness+OVERLAP])
            difference(){
                cylinder(d=gearbox_diameter,h=rotor_height+driven_disc_height+top_thickness+CLEARANCE_MOVE);
                translate([0,0,top_thickness-OVERLAP/2])
                cylinder(d=gearbox_diameter,h=rotor_height+driven_disc_height+top_thickness+CLEARANCE_MOVE+OVERLAP);
                translate([0,0,-OVERLAP/2])
                difference(){
                    cylinder(d=xxx,h=top_thickness+OVERLAP);
                    difference(){
                        cylinder(d=drive_shaft_diameter+CLEARANCE_MOVE+2*top_strut_width,h=top_thickness);
                        cylinder(d=drive_shaft_diameter+CLEARANCE_MOVE,h=top_thickness+OVERLAP);
                    }
                }
            }

            strut_length=xxx/2-drive_shaft_diameter/2;

            translate([0,0,-top_thickness/2])
            for (i=[0:top_struts]){
                rotate([0,0,i*360/top_struts])
                translate([strut_length/2+drive_shaft_diameter/2+top_strut_width/2,0,0])
                cube([strut_length,top_strut_width,top_thickness],center=true);
            }
        }

        outer_perimeter_with_tooth(rotor_height+CLEARANCE_MOVE);

        // we cannot make chamfer much arger than clearance, or the driven disc cannot be inserted. We will use a 45 degree chamfer angle.
        special_chamfer = CLEARANCE_MOVE+0.1;

        translate([0,0,rotor_height+CLEARANCE_MOVE-OVERLAP/2])
        difference(){
            h = driven_disc_height+2*CLEARANCE_MOVE;
            rotate([0,0,degrees_tooth_outer/2]) // to allign artefacts with outer_perimeter_with_tooth()
            cylinder(d=gearbox_diameter,h=h+special_chamfer+layer_resolution);

            translate([0,0,-OVERLAP/2])
            cylinder(d=driven_disc_diameter+2*CLEARANCE_MOVE, h=h);

            translate([0,0,h-OVERLAP])
            cylinder(d1=driven_disc_diameter+2*CLEARANCE_MOVE,d2=driven_disc_diameter+2*CLEARANCE_MOVE-2*special_chamfer, h=special_chamfer+2*OVERLAP);

            translate([0,0,h+special_chamfer])
            cylinder(d=driven_disc_diameter+2*CLEARANCE_MOVE-2*special_chamfer, h=h);
        }
    }
}

module top_cover_legacy(){
    extra = 2; // TODO
    difference(){
        cylinder(d=gearbox_diameter+extra,h=top_thickness);
        translate([0,0,-5])
        cylinder(d=drive_shaft_diameter+2*CLEARANCE_MOVE,h=15);
    }
    translate([0,0,top_thickness])
    difference(){
        cylinder(d=gearbox_diameter+extra,h=rotor_height+driven_disc_height+top_thickness+CLEARANCE_MOVE);
        translate([0,0,-OVERLAP/extra])
        cylinder(d=gearbox_diameter+tolerance,h=rotor_height+driven_disc_height+top_thickness+CLEARANCE_MOVE+OVERLAP);
    }
}

/*********** functions ***********/
function clearance_outline_to_rotor() = showpart(1) && showpart(4) ? CLEARANCE_INPLACE : CLEARANCE_MOVE;

function clearance_shaft_to_rotor() = showpart(5) && showpart(4) ? CLEARANCE_INPLACE : CLEARANCE_MOVE;

function max_overhang() = (1-(quality/100))*2*nozzle_diameter;

function rotor_diameter() = gearbox_diameter-2*tooth_diameter-2*outside_perimeter_width-2*clearance_outline_to_rotor();

function num_rotor_segments() =
    max(1,conf_rotor_segments > 0 ? conf_rotor_segments : rotor_height/layer_resolution);

function showpart(partId) = SHOW_PART==0 ||  SHOW_PART==partId;

function rotor_height() = gearbox_height-2*CLEARANCE_MOVE-top_thickness-driven_disc_height;

function circle_sides(value) = value <= 0 ? $fn : min($fn,value);
```