[User]
Hey, I'm looking to get a parametric wall mount designed for the Ubiquiti Cloud Gateway Ultra. I've got some basic dimensions, but I want to make it configurable, so I need a parametric OpenSCAD design.

Here's the basic info, and some of my design thoughts:

*   **Device Dimensions:** The router, as measured, is about 141.8mm long, 127.6mm wide, and 30mm high. I'd like to add an extra millimeter on all dimensions for easy sliding/fit, so that makes it 142.8mm x 128.6mm x 31mm. Let's call these `router_l`, `router_b`, and `router_h`, respectively.
*   **Mounting:** I envision the router sliding into a frame.
*   **Screw Holes:**  I'd like two counterbored screw holes on the bottom of the mount. They need to be designed for 3mm screws. The distance between these can be determined later, but I'm thinking around 1/3 and 2/3 of the length of the mount. Also, the counterbore needs to be able to fit the screw heads, so lets make them conical.
*   **Airflow:** I would also like to add many small circular cutouts through the back of the mount for airflow.  Let's say 14 columns and 12 rows of 8mm circles, spaced evenly across most of the back. I think an alternating grid pattern where not every hole is present would be good, and let's rotate some of the circles 22.5 degrees in an alternating fashion.
*   **Mounting Holes:** Finally, I need four smaller mounting holes to secure the mount to a wall, one in each corner. Let's make them 5mm in diameter.

I'd like the entire design to be parametric, so I can easily adjust all of these values. So the following is a summary of variables:
*  router_l
*  router_b
*  router_h
*  screwsize
*  hole_diameter (for wall mount holes)

I think that's it for now. Let me know if you need more information. Can you generate an OpenSCAD file for me? Also please ensure it's all designed in a way to easily customize.

[Assistant]
UCG_Ultra_Mount.scad:
```
router_l=141.8+1;
router_b=127.6+1;
router_h=30+1;
screwsize=3;

rotate([90,0,0])
    union(){
        difference(){
            cube([router_l+3,router_b+3,router_h+3]);
            translate([1.5,1.5,1.5])
                cube([router_l,router_b+1.51,router_h]);
            translate([10,10,1.5])
                cube([router_l-20,router_b,router_h+3]);
            translate([10,-0.1,5])
                cube([router_l-20,2,router_h-10]);
            for(x=[1:1:13])
                for(y=[1:1:11])
                    translate([x*(router_l/14),y*(router_b/12),-0.1])
                    if((x % 2 == 0) && (y % 2 == 0)){ rotate([0,0,22.5])
                        cylinder(d=8, h=2.5,$fn=8);
                    } else {
                        cylinder(d=8, h=2.5,$fn=8);
                    };
            translate([router_l/3,router_b-3,-0.1])
                cylinder(d1=screwsize, d2=screwsize*2.5, h=3,$fn=50);
            translate([(router_l/3)*2,router_b-3,-0.1])
                cylinder(d1=screwsize, d2=screwsize*2.5, h=3,$fn=50);

        };
        translate([5,5,-3])
            cylinder(d=5, h=3,$fn=50);
        translate([router_l-5,5,-3])
            cylinder(d=5, h=3,$fn=50);
        translate([router_l-5,router_b-5,-3])
            cylinder(d=5, h=3,$fn=50);
        translate([5,router_b-5,-3])
            cylinder(d=5, h=3,$fn=50);
        translate([router_l/3,router_b-3,-3])
            difference(){
                cylinder(d=screwsize+4, h=3, $fn=50);
                cylinder(d=screwsize, h=3, $fn=50);
            }
        translate([(router_l/3)*2,router_b-3,-3])
            difference(){
                cylinder(d=screwsize+4, h=3, $fn=50);
                cylinder(d=screwsize, h=3, $fn=50);
            }
    }

```


[User]
I'm looking to create a parametric L-bracket with some specific features, and I'd like the design in OpenSCAD. I need a bracket with rounded corners, countersunk holes on both sides, and the ability to customize a few key things.

Essentially, I need to be able to specify:

*   The overall width of the bracket.
*   The thickness of the material.
*   The distance of each hole from the outer edge (both along the 'y' and 'x' axes of the L).
*   The diameter of each hole.
*   The countersink factor for each hole (to control the countersink diameter, where 2x the hole diameter is standard and 1 means no countersink).
*   The thickness of a diagonal support edge that adds strength to the inside corner.
*   The amount of material to cut off the outer edge to create a chamfer.
*   The number of segments used for circles.

I'd like the bracket to be designed for printing on its side for better strength. This means it should be lying "flat" in the design. The design should also account for a little extra material on the inside corner to make it more robust.

Could you provide the OpenSCAD code for this? I'd like the code to be well-commented, and I'd prefer it if the variables are laid out in an organized and readable way.

[Assistant]
ParametricLBracketRoundedCountersunk.scad:
```
// Parametric rounded L-Bracket with countersunk holes
// Copyright 2024 MegaHertz67.
// Released under the Creative Commons - Attribution license.
//
// Design inspired by non-rounded bracket w/o countersunk holes
// (Parametric L bracket by lucibrandus thingiverse 472121)

// Width of bracket (mm)
w = 12; // [0:0.1:30]
// Thickness of bracket (mm)
t = 3; // [0:0.1:12]

// y hole distance from outer edge (mm)
y_hole_dist = 12;  // [1:0.1:50]
// y hole diameter (mm)
y_hole_dia = 3.2;  // [0:0.1:12]
// y hole countersunk factor (2=Standard: Head diameter=2*hole diameter     1=NoCountersunk)
y_hole_csfac = 2;  // [1:0.1:5]
y_hole_csdia=y_hole_dia*y_hole_csfac;  //cs top diameter

// x hole distance from outer edge (mm)
x_hole_dist = 12;  // [1:0.1:50]
// x hole diameter (mm)
x_hole_dia = 3.2;  // [0:0.1:12]
// x hole countersunk factor (2=Standard: Head diameter=2*hole diameter 1=NoCountersunk)
x_hole_csfac = 2;  // [1:0.1:5]
x_hole_csdia=x_hole_dia*x_hole_csfac;  //cs top diameter

// diagonal edge support thickness
d_edge = 1.5; // [0:0.1:8]
// outer edge cutoff
o_edge = 1.0; // [0:0.1:4 ]

// circle segments
$fn=50;  // [4:2:180]

//Lay down for higher strength at print
rotate([0, 90, 0])
translate([-w/2,0,0])
{
difference()
{
	union ()
	{
		//y part
        translate([0, -y_hole_dist/2, t/2])
		cube(size = [w,y_hole_dist,t], center=true);

        translate([0, -y_hole_dist, t/2])
        cylinder(h=t, d=w, center=true);

        // x part
		translate([0, -t/2, x_hole_dist/2])
		cube(size = [w,t,x_hole_dist], center=true);

        translate([0, -t/2, x_hole_dist])
        rotate([90, 0, 0])
        cylinder(h=t, d=w, center=true);
	}

    //y part hole
    translate([0, -y_hole_dist, t/2])
	cylinder(h=t+1, d=y_hole_dia, center=true);

    translate([0, -y_hole_dist, t+.001-y_hole_csdia/2])
	cylinder(h=y_hole_csdia/2, d1=0, d2=y_hole_csdia, center=false);

	// x part hole
    rotate([90, 0, 0])
	translate([0, x_hole_dist, t/2])
	cylinder(h=t+1, d=x_hole_dia, center=true);

    rotate([90, 0, 0])
	translate([0, x_hole_dist, t+.001-x_hole_csdia/2])
	cylinder(h=x_hole_csdia/2, d1=0, d2=x_hole_csdia, center=false);

    //outer edge cut
    rotate([45, 0, 0])
    cube(size = [w+1, o_edge*sqrt(2), o_edge*sqrt(2)], center= true);

}

intersection()  // diagonal edge support
{
    r=d_edge+2*t*sqrt(2);
    difference()
    {
    rotate([45, 0, 0])
    cube(size = [w,r,r], center=true);

    rotate([45, 0, 0])   //outer edge cut
    cube(size = [w+1, o_edge*sqrt(2), o_edge*sqrt(2)], center=true);
    }

translate([0, -r/2-t, r/2+t])
cube(size = [w,r,r], center=true);

}
}
```


[User]
Hi, I'm looking to create a highly customizable hook generator in OpenSCAD. I've seen a few designs out there, but none that really hit all the points I need. I'd like a design where the hook is built up from a series of connected parts: rounded ends, straight segments, and curved sections. I've got a pretty clear idea of how it should work.

Here's the breakdown of the design and the parameters I'd like to control:

**General Parameters:**

*   `hook_width`: The overall width of the hook.
*   `hook_thickness`: The thickness of the hook material.
*   `rounding_radius`: A radius for rounding sharp edges, used on the ends and the corners of rectangular parts.
*   `part10_screw_nest_enable`: A boolean flag to enable or disable a screw nest in part 10 of the hook.
*   `part10_is_last`: A boolean flag to disable all parts after part 10, to allow for easy end-of-hook screw mounting without having to manually make all the other lengths and angles zero.

**Shape Parameters (the hook is composed of 23 parts):**

*   Parts 0 and 22: These are rounded endings and don't have parameters beyond the general `rounding_radius`.
*   Parts 1, 3, 5, 7, 9, 11, 13, 15, 17, 19, and 21 are all arc segments. Each of these should have two parameters:
    *   `rotation_radiusN` (where N is the part number): The radius of the arc.
    *   `rotation_angleN`: The angle of the arc (in degrees).
*   Parts 2, 4, 6, 8, 10, 12, 14, 16, 18, and 20 are straight segments. Each has a single parameter:
    *   `straightN` (where N is the part number): The length of the straight segment.

**Screw Hole Parameters (only for the screw nest in part 10):**

*   `screw_offset`: Distance of the center of the screw hole from the beginning of the straight segment (part 10).
*   `screw_head_dia`: Diameter of the screw head.
*   `screw_leg_dia`: Diameter of the screw shank. It should be slightly larger than the real diameter for tolerance.
*   `screw_head_h`: Height of the screw head.
*   `screw_head_drop`: How much the screw head should sink below the surface.

**Supporting Parameters:**

*   `$fn`: General number of circle fragments for smooth curves.
*   `fn_rounding`: Number of circle fragments for the rounding operation.
*    `color_parts`: Bool to turn on coloring of each part, useful for preview

**Additional Requirements:**

*   I'd like the final hook to be a single solid model, not separate pieces.
*   I would prefer to avoid external libraries if at all possible.
*   The parts are connected end-to-end. When doing rotations and translations, the base of the next part should be at the exact end of the previous part. It should work like a chain.
*   Please ensure that the hook is generated such that the base of the hook (part 0) is at 0,0,0 so it is easy to orient.

I think that's everything. Let me know if you need clarification on any aspect of this project, and thanks so much in advance!

[Assistant]
any-hook-generator.scad:
```
/* Any-hook generator (fully customizable)
   by torwan @ April 1st, 2024

   - v1.0 (15th March 2024): Initial version.
   - v1.1 (1st April 2024):
     - Added slight overlap between the sub-parts (as big as a value
       of "cc" is) to make sure that a final hook is a "one body" model.
     - Added "part10_is_last" to disable all parts behind Part 10 (when
       True). This may be helpful when you want to use a screw and a screw
       hole in the Part 10 and don't want to waste time on zeroing all
       parameters of the remaining parts behind the Part 10. Thanks to
       **filipemeiracastro** (Thingiverse) for suggesting this!
*/

/* Description / Hints:
   - See more details on https://www.thingiverse.com/thing:6534190
     or on https://github.com/torwanbukaj/any-hook-generator
   - All dimensions in [mm].
   - To generate STL file, render the object using F6 and save it
     using F7.
   - $fn controls number of a circle fragments. I recommend to use
     $fn = 100 or more.
   - PRINTING RECOMMENDATIONS: When slicing, increase wall count
     (wall thickness) in a way that there is no infill between
     the outer walls. From my experience, this helps the printed
     hooks to be more flexible and to keep their initial shape
     after exposing them to some (even significant) forces.
     Infill will work against flexibility.
   - Every hook consists of interconnected 23 parts: rounded endings,
     straight bars and arcs. Length of each straight part, as well as
     angle and radius of each arcs can be modified.
   - You can influence the shape of a hook by modifying parameters in
     the section "Model shape parameters"
*/

// ---------- Model general parameters -----------
/* [Model general parameters] */
// Hook width
hook_width = 10.0;

// Hook thickness
hook_thickness = 3.0;

// Rounding radius for smoothing sharp edges
rounding_radius = 0.5;

// Enable screw nest in Part 10
part10_screw_nest_enable = false;

// Disable all Parts behind Part 10
part10_is_last = false;

// ------------ Model shape parameters ----------
// Numbering of the individual parts of a hook:
/*
                                  ____   ___________
                                 | 22 | / | 18 |    \
                                 |____|/19|____|_ 17 \
              ____________        \ 21|___/      \____\
             /  |  6   |  \        \  |20/        |   |
            / 5/_______| 7/\        \_|_/         |   |
           /__/         \/8/\ ________            |   |
          |   |          \/ 9|  10  | \           |16 |
          | 4 |           \__|______|11\          |   |
          |___|          __          \__\         |   |
          \   \         /0 \          \12\        |___|
           \ 3 \_______/\__/           \__\_______/15/
            \  |   2  | 1 /             \13  |14 |  /
             \_|______|__/               \___|___|_/

Parts 0 and 22 are just rounded endings on both sides and do not
require any parametrization.
*/

/* [Model shape parameters] */

// Part 1 radius:
rotation_radius1 = 3.5;
// Part 1 angle:
rotation_angle1 = 45;

// Part 2 length:
straight2 = 5.0;

// Part 3 radius:
rotation_radius3 = 3.5;
// Part 3 angle:
rotation_angle3 = 90;

// Part 4 length:
straight4 = 7.0;

// Part 5 radius:
rotation_radius5 = 3.5;
// Part 5 angle:
rotation_angle5 = 90;

// Part 6 length:
straight6 = 5.0;

// Part 7 radius:
rotation_radius7 = 0.5;
rotation_angle7 = 45;

// Part 8 length:
straight8 = 5.0;

// Part 9 radius:
rotation_radius9 = 0.5;
// Part 9 angle:
rotation_angle9 = 45;

// Part 10 length:
straight10 = 10.0;

// Part 11 radius:
rotation_radius11 = 0.5;
// Part 11 angle:
rotation_angle11 = 45;

// Part 12 length:
straight12 = 3.0;

// Part 13 radius:
rotation_radius13 = 0.5;
// Part 13 angle:
rotation_angle13 = 45;

// Part 14 length:
straight14 = 4.0;

// Part 15 radius:
rotation_radius15 = 3.5;
// Part 15 angle:
rotation_angle15 = 90;

// Part 16 length:
straight16 = 6.0;

// Part 17 radius:
rotation_radius17 = 3.5;
// Part 17 angle:
rotation_angle17 = 90;

// Part 18 length:
straight18 = 4.0;

// Part 19 radius:
rotation_radius19 = 1.0;
// Part 19 angle:
rotation_angle19 = 35;

// Part 20 length:
straight20 = 4.0;

// Part 21 radius:
rotation_radius21 = 1.0;
// Part 21 angle:
rotation_angle21 = 35;

// ----------- Screw-holes dimensions ------------
/* [Screw-holes dimensions] */

//Distance of the screw nest from the beginning of a part
screw_offset = 5.0;

// Screw head diameter
screw_head_dia = 6.4;

// Screw leg diameter (make it 0.1-0.2 bigger than real)
screw_leg_dia = 3.3;

// Screw head height
screw_head_h = 2.6;

// How much a screw has to drop into material (hiding head)
screw_head_drop = 0.2;

// ------------ Supporting parameters ------------
/* [Supporting parameters] */
// General number of a circle fragments
$fn = 100;

// Number of a circle fragments for rounding (stay rather low)
fn_rounding = 20;

// TRUE  -> every part in different color in the pre-view, FALSE - one color
color_parts = true;

// ------------- Helping parameters --------------
// (do not modify below parameters)
/* [Hidden] */
cc = 0.01;

rotation_radius11c = part10_is_last ? 0 : rotation_radius11;
rotation_angle11c = part10_is_last ? 0 : rotation_angle11;

straight12c = part10_is_last ? 0 : straight12;

rotation_radius13c = part10_is_last ? 0 : rotation_radius13;
rotation_angle13c = part10_is_last ? 0 : rotation_angle13;

straight14c = part10_is_last ? 0 : straight14;

rotation_radius15c = part10_is_last ? 0 : rotation_radius15;
rotation_angle15c = part10_is_last ? 0 : rotation_angle15;

straight16c = part10_is_last ? 0 : straight16;

rotation_radius17c = part10_is_last ? 0 : rotation_radius17;
rotation_angle17c = part10_is_last ? 0 : rotation_angle17;

straight18c = part10_is_last ? 0 : straight18;

rotation_radius19c = part10_is_last ? 0 : rotation_radius19;
rotation_angle19c = part10_is_last ? 0 : rotation_angle19;

straight20c = part10_is_last ? 0 : straight20;

rotation_radius21c = part10_is_last ? 0 : rotation_radius21;
rotation_angle21c = part10_is_last ? 0 : rotation_angle21;

// ------------- Helping parameters --------------
// (do not modify below parameters)

part0_col  =  color_parts ? "Gold" : "Gold";
part1_col  =  color_parts ? "Yellow" : "Gold";
part2_col  =  color_parts ? "Olive" : "Gold";
part3_col  =  color_parts ? "DarkKhaki" : "Gold";
part4_col  =  color_parts ? "BurlyWood" : "Gold";
part5_col  =  color_parts ? "RosyBrown" : "Gold";
part6_col  =  color_parts ? "Coral" : "Gold";
part7_col  =  color_parts ? "Goldenrod" : "Gold";
part8_col  =  color_parts ? "Chocolate" : "Gold";
part9_col  =  color_parts ? "MistyRose" : "Gold";
part10_col =  color_parts ? "Maroon" : "Gold";
part11_col =  color_parts ? "Goldenrod" : "Gold";
part12_col =  color_parts ? "BurlyWood" : "Gold";
part13_col =  color_parts ? "Yellow" : "Gold";
part14_col =  color_parts ? "DarkKhaki" : "Gold";
part15_col =  color_parts ? "Chocolate" : "Gold";
part16_col =  color_parts ? "MistyRose" : "Gold";
part17_col =  color_parts ? "Maroon" : "Gold";
part18_col =  color_parts ? "Goldenrod" : "Gold";
part19_col =  color_parts ? "BurlyWood" : "Gold";
part20_col =  color_parts ? "Yellow" : "Gold";
part21_col =  color_parts ? "Olive" : "Gold";
part22_col =  color_parts ? "Maroon" : "Gold";

// --------------- GENERATION AREA ---------------

rotate([0, 90, 0])
    generate_hook();

// ------------------ MODULES --------------------
// (you do not need to touch anything below unless you
// know what you do :) )

module generate_hook()
{
add_turn_lu(angle = rotation_angle21c, radius = rotation_radius21c, color = part21_col)
add_straight(length = straight20c, color = part20_col)
add_turn_ld(angle = rotation_angle19c, radius = rotation_radius19c, color = part19_col)
add_straight(length = straight18c, color = part18_col)
add_turn_ld(angle = rotation_angle17c, radius = rotation_radius17c, color = part17_col)
add_straight(length = straight16c, color = part16_col)
add_turn_ld(angle = rotation_angle15c, radius = rotation_radius15c, color = part15_col)
add_straight(length = straight14c, color = part14_col)
add_turn_ld(angle = rotation_angle13c, radius = rotation_radius13c, color = part13_col)
add_straight(length = straight12c, color = part12_col)
add_turn_lu(angle = rotation_angle11c, radius = rotation_radius11c, color = part11_col)
add_straight(length = straight10, color = part10_col, screw_nest = part10_screw_nest_enable)
add_turn_ld(angle = rotation_angle9, radius = rotation_radius9, color = part9_col)
add_straight(length = straight8, color = part8_col)
add_turn_lu(angle = rotation_angle7, radius = rotation_radius7, color = part7_col)
add_straight(length = straight6, color = part6_col)
add_turn_lu(angle = rotation_angle5, radius = rotation_radius5, color = part5_col)
add_straight(length = straight4, color = part4_col)
add_turn_lu(angle = rotation_angle3, radius = rotation_radius3, color = part3_col)
add_straight(length = straight2, color = part2_col)
add_turn_lu(angle = rotation_angle1, radius = rotation_radius1, color = part1_col)
make_rounded_end(color = part0_col);

make_rounded_end(color = part22_col);
}

module add_turn_ld(angle = 5, radius = 2, color = "Gold")
{
    translate([0, cc, -hook_thickness])
    rotate([angle, 0, 0])
    {
        ty = radius * sin(angle);
        tz = hook_thickness + radius * (1 - cos(angle));
        translate([0, -ty, tz])
        {
            // Previous parts
            children();

            // New part being added
            color(color)
            translate([0, 0, 0])
                prepare_arc(rot_r = radius,
                            rot_ang = angle,
                            rot_part = 0,
                            part_type = "ld");
        }
    }
}

module add_turn_lu(angle = 5, radius = 2, color = "Gold")
{
    translate([0, cc, 0])
    rotate([-angle, 0, 0])
    {
        ty = radius * sin(angle);
        tz = radius * (1 - cos(angle));
        translate([0, -ty, -tz])

        {
            // Previous parts
            children();

            // New part being added
            color(color)
            translate([0, 0, 0])
                prepare_arc(rot_r = radius,
                            rot_ang = angle,
                            rot_part = 0,
                            part_type = "lu");
        }
    }
}

module add_straight(length = 2, color = "Gold", screw_nest = false)
{
    translate([0, -length+cc, 0])
    {
        // Previous parts
        children();

        // New part being added
        color(color)
        translate([0, 0, -hook_thickness])
            make_straight(len = length, screw_nest = screw_nest);
    }
}

module make_rounded_end(color = "Gold")
{
    color(color)
    translate([0, 0, -hook_thickness/2])
        rotate([0, 90, 0])
            translate([0, 0, rounding_radius+cc/4])
                minkowski()
                    {
                        cylinder(d = hook_thickness-2*rounding_radius,
                                 h = hook_width-2*rounding_radius-cc/2);
                        sphere(r = rounding_radius);
                    }
}

module prepare_arc(rot_r = 0, rot_ang = 0, rot_part = 0, part_type = "")
{
    rotate([-rot_part, 0, 0])
        prepare_arc_preorient();

    module prepare_arc_preorient()
    {
        if (part_type == "lu")
                translate([0, 0, -hook_thickness])
                    make_arc(rot_r = rot_r, rot_ang = rot_ang);

        if (part_type == "ld")
                mirror([0, 0, 1])
                    make_arc(rot_r = rot_r, rot_ang = rot_ang);
    }
}

module make_arc(rot_r = 0, rot_ang = 0)
{
translate([0, 0, rot_r+hook_thickness])
    rotate([0, 90, 0])
        rotate_extrude(angle = rot_ang)
            translate([rot_r, 0, 0])
                hook_cs_blueprint();
}

module make_straight(len = 0, screw_nest = false)
{
    difference()
    {
        translate([hook_width, 0, hook_thickness])
            rotate([0, 90, 90])
                linear_extrude(len)
                    hook_cs_blueprint();
        if (screw_nest == true)
            translate([hook_width/2, len-screw_offset, hook_thickness+cc/2])
                rotate([180, 0, 0])
                    screw_nest(head_dia = screw_head_dia,
                               head_drop = screw_head_drop,
                               screw_head_h = screw_head_h,
                               total_length = hook_thickness+cc,
                               screw_leg_dia = screw_leg_dia);
    }
}

module hook_cs_blueprint()
{
    translate([rounding_radius, rounding_radius, 0])
        offset(r = rounding_radius, $fn = fn_rounding)
            square([hook_thickness-2*rounding_radius,
                    hook_width-2*rounding_radius]);
}

module screw_nest(head_dia = 6,
                  head_drop = 1,
                  screw_head_h = 3,
                  total_length = 10,
                  screw_leg_dia = 2) // Template for space for a mounting screw
{
    rotate_extrude(angle = 360)
        polygon([[0, 0],
                 [head_dia/2, -cc],
                 [head_dia/2, head_drop],
                 [screw_leg_dia/2, head_drop + screw_head_h],
                 [screw_leg_dia/2, total_length+cc],
                 [0, total_length+cc]
                ]);
}
```


[User]
I'm looking to create a customizable gutter filter, also known as a leaf catcher, for my downspout. I have a specific downspout drain diameter and would like to be able to adjust the filter's leg size to fit, as well as add a rim to prevent it from falling through the drain.

The base of the filter should be a scaled version of the "MK6_Gutter_Filter_Final_repaired.stl" file. I'd like a way to input my downspout drain diameter and have the filter scale accordingly. Specifically, the largest diameter of the filter legs should scale to match the specified downspout diameter. So, if my downspout drain is 56mm, the widest part of the legs should be scaled down to that. The original design has a max leg diameter of 75mm.

I'd also like to add a circular rim to the top of the filter. This rim should have a customizable radius and thickness, and it should sit on top of the scaled filter design. I need to be able to control the radius (how far it extends past the main filter body) and the thickness of this rim. The rim will function by being wider than the drain, thus preventing the filter from falling all the way down the pipe.

Here's a summary of the parameters I need to control:

*   `downspout_drain_diameter_mm`: The diameter of my downspout drain in millimeters. This will be used to scale the legs of the filter.
*   `rim_plate_radius_mm`: The radius of the rim plate in millimeters. This will be added on to the radius of the main body.
*   `rim_plate_thickness_mm`: The thickness of the rim plate in millimeters.

The other constants in my existing code are not meant to be modified by the user, but I'll include them here for reference (although these should probably be implemented as constants in your code, too):

*   `default_gutter_max_leg_diameter_mm = 75;`
*   `default_gutter_bottom_ring_inner_diameter_mm = 59;`
*   `default_gutter_bottom_ring_outer_diameter_mm = 64;`

Could you generate the necessary OpenSCAD files for this? I'll need at least two files: one for the main filter with scaling and one for the rim. I'd like to import the STL file into the main file, and use a scale modifier based on the user supplied `downspout_drain_diameter_mm`. I also want the rim file to be easily callable into the main file (so that the rim sits on top of the main scaled gutter). Please be sure to use good programming practices, and comments in the code when needed. I'm going to be using this with the "MK6_Gutter_Filter_Final_repaired.stl" file that I have.

[Assistant]
gutter_filter_modified.scad:
```
rim_plate_radius_mm = 6;
rim_plate_thickness_mm = 3;

// Provide your downspout drain hole diameter in mm.
// You can go measure it with a caliper.
// The original gutter filter will be scaled to fit the end of the legs into the hole.
// If you plan to trim part of the legs off, you want to "increase" this number such that post-trim, it would fit your downspout hole.
downspout_drain_diameter_mm = 56;

///////////////////////////////////////////////////

//Do not change these.
default_gutter_max_leg_diameter_mm = 75;

//Do not change these.
default_gutter_bottom_ring_inner_diameter_mm = 59;

//Do not change these.
default_gutter_bottom_ring_outer_diameter_mm = 64;

//Do not change these.
$fn = 20;

scale_factor = downspout_drain_diameter_mm / default_gutter_max_leg_diameter_mm;

module default_gutter_filter() {
    // Max diameter at the foot is 74.786mm via PrusaSlicer.
    // Round it up to 75mm for simplicity/give some margin of error.
    import("MK6_Gutter_Filter_Final_repaired.stl");
}

module scale_gutter_filter(sf) {
    // Assumes children are default_gutter_filter instance and its rim.
    scale([sf, sf, sf])
    children();
}

module rim() {
    // Since the whole figure can be downscaled/upscaled, we attempt to maintain fidelity
    // to user specified rim plate radius and thickness by upscaling right here.
    reciprocal_scale_factor = 1/scale_factor;
    linear_extrude(height=rim_plate_thickness_mm * reciprocal_scale_factor) {
        difference() {
            offset(r=rim_plate_radius_mm * reciprocal_scale_factor) {
                circle(r=default_gutter_bottom_ring_outer_diameter_mm/2);
            }

            circle(r=default_gutter_bottom_ring_outer_diameter_mm/2);
        }
    }
}

scale_gutter_filter(scale_factor) {
    default_gutter_filter();
    translate([0, 0, 40])
    rim();
}

```


[User]
I'd like to design a hook for my bathroom radiator, similar to the one I saw on Thingiverse (thing:5294230), but I'd like it to be parametric so I can adjust it for different radiator sizes. I've got a Zehnder radiator with 23.5mm diameter tubes that are 36mm apart, center-to-center.

The basic idea is a hook that clamps onto two of the radiator tubes. I want to be able to adjust the tube diameter, the center-to-center distance of the tubes, and the width of the hook. I'd also like to be able to control the 'strength' of the clamping mechanism (basically, how tightly it grips the tubes), and also the diameter of the actual hook part, where you hang things. I'd like a little bit of overlap on the clamp to ensure it stays put. A chamfer on the edges of the hook would be nice too.

Could you generate an OpenSCAD file for this? I'd like to have separate variables for:

*   `radiator_tube_dia`: Diameter of the radiator tubes.
*   `radiator_tube_dist`: Center-to-center distance between radiator tubes.
*  `radiator_tube_len`: Length of a single radiator tube
*   `hook_width`: Width of the hook.
*   `hook_gap`: A gap between the hook and radiator tube (can be positive or negative)
*   `hook_strength`: Thickness of the clamping arms.
*   `hook_dia`: Diameter of the hook itself.
*   `hook_angle_overlap`: Angle of the overlap to ensure it stays in place.
*  `hook_chamfer`: Chamfer on the edges of the hook.
*   `hook_fn`:  Number of faces/segments for the circles that make up the hook.
* `radiator_tube_fn`: Number of faces/segments for the circles that make up the radiator tube

I think those should cover it.

[Assistant]
home_hook_for_bathroom_wall_radiators.scad:
```
////////////////////////////////////////////////////////////////////////////////////////////////////
// Project  Home hook for bathroom wall radiators
// File     home_hook_for_bathroom_wall_radiators.scad
// Content  Top Level Design Entry
// Author   Dirk Mehlfeldt
////////////////////////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////////////////////////
// explicite parameter // explicite parameter // explicite parameter // explicite parameter // expli
////////////////////////////////////////////////////////////////////////////////////////////////////

/* [Design Options] */

// Design Target
design_option_target = "Show"; // [Show, Print, Test]
// Design Simplification
design_option_simplify_id = 0; // [0:Detailed, 1:Simple]

/* [View and Intersection] */

// Test Intersection Enable
test_intersection_enable = false;
// Test Intersection Origin
test_intersection_origin = [0.0, 0.0, 0.0]; // [-400.0 : 400.0]
// Test Intersection Rotation
test_intersection_rotation = [0.0, 0.0, 0.0]; // [-180.0 : 180.0]
// Test Intersection Position
test_intersection_position = [-50.0, 0.0, 0.0]; // [-400.0 : 400.0]
// Test Intersection Size
test_intersection_size = [100.0, 100.0, 300.0]; // [-500.0 : 500.0]

// Explode Distance
design_option_explode_dist = 0.0; // [0 : 25 : 150]

/* [Design Element Types] */

// Enable radiator
design_option_enable_radiator = true; // [false, true]
// Color of radiator
design_option_color_radiator= "White"; // [White, Magenta, Purple, DeepPink, Blue, Red, Lime, LimeGreen, Orange, Gold, Yellow, Silver, Grey, DimGrey, BurlyWood]
// Alpha radiator
design_option_alpha_radiator = 1.0; // [0.0 : 0.1 : 1.0]

// Enable hook
design_option_enable_hook = true; // [false, true]
// Color of hook
design_option_color_hook = "Orange"; // [Magenta, Purple, DeepPink, Blue, Red, Lime, LimeGreen, Orange, Gold, Yellow, Silver, Grey, DimGrey, BurlyWood]
// Alpha hook
design_option_alpha_hook = 1.0; // [0.0 : 0.1 : 1.0]

/* [Design Parameter for Radiator] */

// Radiator Tube Diameter
radiator_tube_dia = 23.5; // [10.0 : 0.1 : 37.0]
// Radiator Tube (Center) Distance
radiator_tube_dist = 36.0; // [20.0 : 0.1 : 52.0]
// Radiator Tube Length
radiator_tube_len = 40.0; // [20.0 : 10.0 : 60.0]
// Radiator Tube Faces
radiator_tube_fn = 24; // [16 : 32]

/* [Design Parameter for Hook] */

// hook width
hook_width = 15.0; // [5.0 : 1.0 : 15.0]
// hook fit_gap
hook_gap = 0.0; // [-1.0 : 0.1 : 1.0]
// hook strength
hook_strength = 3.0; // [1.0 : 0.2 : 5.0]
// hook dia
hook_dia = 20.0; // [10.0 : 1.0 : 30.0]
// hook angular overlap
hook_angle_overlap = 15; // [10 : 1 : 20.0]
// hook_chamfer
hook_chamfer = 1.0; // [0.0 : 0.1 : 2.0]
// hook Faces
hook_fn = 32; // [24 : 48]

////////////////////////////////////////////////////////////////////////////////////////////////////
// implicite parameter // implicite parameter // implicite parameter // implicite parameter // impli
////////////////////////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////////////////////////
// dependencies // dependencies // dependencies // dependencies // dependencies // dependencies // d
////////////////////////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////////////////////////
// functions // functions // functions // functions // functions // functions // functions // functi
////////////////////////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////////////////////////
// modules // modules // modules // modules // modules // modules // modules // modules // modules /
////////////////////////////////////////////////////////////////////////////////////////////////////

// octahedron for chamfers etc
// ohrad = radius of octahedron corners
// (0, 0, 0) in center
module octahedron(ohdia)
{
   polyhedron
   (
      points = 0.5 * ohdia * [[ 1,  0,  0], [-1,  0,  0], [ 0,  1,  0], [ 0, -1,  0], [ 0,  0,  1], [ 0,  0,  -1]],
      faces  = [[4, 2, 0], [4, 1, 2], [4, 3, 1], [4, 0, 3], [0, 2, 5], [2, 1, 5], [1, 3, 5], [3, 0, 5]]
   );
}

module radiator()
{
   if (design_option_alpha_radiator > 0.0)
   {
      color(c = design_option_color_radiator, alpha = design_option_alpha_radiator)
      {
         rotate(a = [0, -90, 0])
            linear_extrude(height = radiator_tube_len, center = true, convexity = 10, twist = 0, slices = 1, scale = 1.0, $fn = 1)
               for (zpos = [-0.5 * radiator_tube_dist, 0.5 * radiator_tube_dist])
                  translate(v = [zpos, 0.0])
                     circle(d = radiator_tube_dia, $fn = radiator_tube_fn);
      }
   }
}

module hook_2d()
{
   translate(v = [ 0.5 * radiator_tube_dist, 0.0])
      intersection()
      {
         difference()
         {
            circle(d = 1.0 * radiator_tube_dia + 2.0 * hook_gap + 2.0 * hook_strength, $fn = hook_fn);
            circle(d = 1.0 * radiator_tube_dia + 2.0 * hook_gap + 0.0 * hook_strength, $fn = hook_fn);
         }
         union()
         {
            rotate(a = asin((1.0 * radiator_tube_dia + 2.0 * hook_gap + 1.0 * hook_strength) / radiator_tube_dist))
               translate(v = [ 1.0 * radiator_tube_dia,  1.0 * radiator_tube_dia])
                  square(size = 2.0 * radiator_tube_dia, center = true);
            rotate(a = 90 + hook_angle_overlap)
               translate(v = [ 1.0 * radiator_tube_dia,  1.0 * radiator_tube_dia])
                  square(size = 2.0 * radiator_tube_dia, center = true);
         }
      }

   translate(v = [0.0, 0.0])
      rotate(a = asin((1.0 * radiator_tube_dia + 2.0 * hook_gap + 1.0 * hook_strength) / radiator_tube_dist))
         square(size = [sqrt(pow(radiator_tube_dist, 2.0) - pow(1.0 * radiator_tube_dia + 2.0 * hook_gap + 1.0 * hook_strength, 2.0)) + 0.0 * hook_chamfer, hook_strength], center = true);

   translate(v = [-0.5 * radiator_tube_dist, 0.0])
      intersection()
      {
         difference()
         {
            circle(d = 1.0 * radiator_tube_dia + 2.0 * hook_gap + 2.0 * hook_strength, $fn = hook_fn);
            circle(d = 1.0 * radiator_tube_dia + 2.0 * hook_gap + 0.0 * hook_strength, $fn = hook_fn);
         }
         union()
         {
            rotate(a = asin((1.0 * radiator_tube_dia + 2.0 * hook_gap + 1.0 * hook_strength) / radiator_tube_dist))
               translate(v = [-1.0 * radiator_tube_dia, -1.0 * radiator_tube_dia])
                  square(size = 2.0 * radiator_tube_dia, center = true);
            rotate(a = 90 + hook_angle_overlap)
               translate(v = [-1.0 * radiator_tube_dia, -1.0 * radiator_tube_dia])
                  square(size = 2.0 * radiator_tube_dia, center = true);
         }
      }

   translate(v = [-0.5 * radiator_tube_dist, 0.0])
      rotate(a = 45)
         translate(v = [0.0, -(0.5 * radiator_tube_dia + 1.0 * hook_gap + 0.5 * hook_strength) - 0.5 * hook_dia - 0.5 * hook_strength])
            intersection()
            {
               difference()
               {
                  circle(d = 1.0 * hook_dia + 2.0 * hook_strength, $fn = radiator_tube_fn);
                  circle(d = 1.0 * hook_dia + 0.0 * hook_strength, $fn = radiator_tube_fn);
               }
               union()
               {
                  rotate(a = 0)
                     translate(v = [-1.0 * hook_dia,  1.0 * hook_dia])
                        square(size = 2.0 * hook_dia, center = true);
               }
            }
   hull()
   {
      translate(v = [-0.5 * radiator_tube_dist, 0.0])
         rotate(a = 45)
            translate(v = [-0.5 * hook_dia - 0.5 * hook_strength, -(0.5 * radiator_tube_dia + 1.0 * hook_gap + 0.5 * hook_strength) - 0.5 * hook_dia - 0.5 * hook_strength])
               circle(d = hook_strength, $fn = 12);
      translate(v = [-0.5 * radiator_tube_dist, 0.0])
         rotate(a = asin((1.0 * radiator_tube_dia + 2.0 * hook_gap + 1.0 * hook_strength) / radiator_tube_dist))
            translate(v = [-(0.5 * radiator_tube_dia + 1.0 * hook_gap + 0.5 * hook_strength), 0.0])
               circle(d = hook_strength, $fn = 12);
   }

}

module hook()
{
   if (design_option_alpha_hook > 0.0)
   {
      color(c = design_option_color_hook, alpha = design_option_alpha_hook)
      {
         translate(v = [0.0, 0.0, 0.0])
            rotate(a = [0, -90, 0])
               minkowski()
               {
                  linear_extrude(height = hook_width - 2 * hook_chamfer, center = true, convexity = 10, twist = 0, slices = 1, scale = 1.0, $fn = 1)
                     offset(r = -1.0 * hook_chamfer)
                        hook_2d();
                  union()
                  {
                     for (a = [0, 180])
                        rotate(a = [a, 0, 0])
                           cylinder(d1 = 2 * hook_chamfer, d2 = 0.0, h = 1 * hook_chamfer, center = false, $fn = 12);
                  }
               }
      }
   }
}

////////////////////////////////////////////////////////////////////////////////////////////////////
// show // show // show // show // show // show // show // show // show // show // show // show // s
////////////////////////////////////////////////////////////////////////////////////////////////////

module show()
{
   translate(v = [0.0, 0.0, 0.0])
      rotate(a = [0, 0, 0])
         if (design_option_enable_radiator)
            radiator();

   translate(v = [0.0, 0.0, 0.0])
      rotate(a = [0, 0, 0])
         if (design_option_enable_hook)
            hook();
}

////////////////////////////////////////////////////////////////////////////////////////////////////
// print // print // print // print // print // print // print // print // print // print // print /
////////////////////////////////////////////////////////////////////////////////////////////////////

module print()
{
   design_option_simplify_id = 0;

   translate(v = [0.0, 0.0, 0.5 * hook_width])
      rotate(a = [0, 90, 0])
         hook();
}

////////////////////////////////////////////////////////////////////////////////////////////////////
// test // test // test // test // test // test // test // test // test // test // test // test // t
////////////////////////////////////////////////////////////////////////////////////////////////////

module test()
{
}

////////////////////////////////////////////////////////////////////////////////////////////////////
// main // main // main // main // main // main // main // main // main // main // main // main // m
////////////////////////////////////////////////////////////////////////////////////////////////////

if ($preview)
{
   if (design_option_target == "Show")
      intersection()
      {
         translate(v = [0.0, 0.0, 0.0])
            show();
         if (test_intersection_enable)
            translate(test_intersection_origin)
               rotate(test_intersection_rotation)
                  translate(test_intersection_position)
                     cube(test_intersection_size, center = true);
      }
   else if (design_option_target == "Print")
      print();
   else if (design_option_target == "Test")
      test();
}
else
{
   if (design_option_target == "Show")
      intersection()
      {
         translate(v = [0.0, 0.0, 0.0])
            show();
         if (test_intersection_enable)
            translate(test_intersection_origin)
               rotate(test_intersection_rotation)
                  translate(test_intersection_position)
                     cube(test_intersection_size, center = true);
      }
   else if (design_option_target == "Print")
      print();
   else if (design_option_target == "Test")
      test();
}

////////////////////////////////////////////////////////////////////////////////////////////////////
// muell // muell // muell // muell // muell // muell // muell // muell // muell // muell // muell /
////////////////////////////////////////////////////////////////////////////////////////////////////

module muell()
{
}

```


[User]
Hey, I'm looking for some help designing a resin funnel for 3D printing. I want it to be parametric so I can easily adjust the size for different filters and resin bottles.

I've got a pretty good idea of what I want. Basically, it's a funnel with a top opening, a middle section, and a bottom spout. The key thing is that I want it to have "innie" flutes – you know, channels that run down the inside rather than fins sticking out the side. It's like the opposite of a typical muffin tin, I guess. These flutes help with airflow.

Here's the kind of parameters I'd like to be able to control:

*   `top_radius`:  The radius of the top opening of the funnel.
*   `middle_radius`: The radius at the transition point where the funnel starts narrowing down to the spout.
*   `bottom_radius`: The radius of the spout opening.
*   `thickness`:  The thickness of the funnel walls.
*   `top_height`:  The height of the top conical section.
*   `bottom_height`: The height of the bottom conical section.
*   `flute_radius`:  The radius of the flutes.
*   `smoothness`: Number of segments for smooth circles and cylinders.

I'm thinking something like three flutes evenly spaced. I think that's enough. I'm not sure how best to design them, but maybe you can add some curvature to the flutes where they transition from the middle part to the top and bottom. I'm envisioning a bend where the flute curves into the conical portion, like a smooth "S" shape, rather than a sharp angle.

I'd like the script to generate a single `.scad` file. I don't think I need any external libraries for this.

Can you help me with this?

[Assistant]
Resin_Filter_Funnel.scad:
```
// Resin Filter Funnel
//
// This project started as a set of parameters for Luu Lac's Smart Funnel.
// The goal was to make a funnel that fits for common resin filters.
//
// However, there were some geometry issues, and the resulting model was broken.
//
// What follows is a near total rewrite, which seems to be better behaved for a
// wide variety of parameters.
//
// - Audi

// The following parameters will make a funnel that fits common resin filters.

top_radius = 60;
middle_radius = 14;
bottom_radius = 12;

thickness = 2;
top_height = 60;
bottom_height = 20;
flute_radius = 2.0;
smoothness = 32;

$fn = smoothness;

module flutes(inner_radius) {

	outter_radius = flute_radius + thickness/2;
	bend_radius = 5;

	bottom_dx = middle_radius - bottom_radius;
	bottom_angle = 90 - atan(bottom_height / bottom_dx);
	bottom_length = sqrt(bottom_dx*bottom_dx + bottom_height*bottom_height) + thickness;

	top_dx = top_radius - middle_radius;
	top_angle = (90 - atan(top_height / top_dx)) - bottom_angle;
	top_length = sqrt(top_dx*top_dx + top_height*top_height);

	bend_x = bend_radius + outter_radius;
	upper_dx = bend_x * cos(top_angle) - .01;
	upper_dz = bend_x * sin(top_angle) - .01;

	for (theta = [0:120:240]) rotate([0, 0, theta]) // make three flutes, 120 degrees apart
		translate([bend_radius + flute_radius + middle_radius, 0, -upper_dz / 2])
			rotate([0, -bottom_angle, 180]) { // make one flute and rotate it into the correct orientation
				// upper pipe
				translate([upper_dx, 0, upper_dz])
					rotate([0, -top_angle, 0])
						difference() {
							cylinder(h=top_length, r=outter_radius);
							translate([0, 0, -.01]) cylinder(h=top_length/2 + .02, r=inner_radius);
						}
				// bend
				rotate([90, 0, 0])
					difference() {
						// torus - outter wall
						rotate_extrude(angle=top_angle)
							translate([bend_x, 0, 0]) circle(r=outter_radius);
						// torus - inner wall
						rotate_extrude()
							translate([bend_x, 0, 0]) circle(r=inner_radius);
					}
				// lower pipe
				translate([bend_x, 0, -bottom_length + .01])
					difference() {
						cylinder(h=bottom_length, r=outter_radius);
						translate([0, 0, -.01]) cylinder(h=bottom_length + .02, r=inner_radius);
					}
			}
}

module funnel() {

	// make funnel
	difference() {
		// solid models
		union() {
			// top cone
			cylinder(h=top_height, r1=middle_radius, r2=top_radius);
			// bottom cone
			translate([0, 0, -bottom_height])
				cylinder(h=bottom_height, r1=bottom_radius, r2=middle_radius);
		}
		// bits to remove
		union() {
			// top inside cone
			translate([0, 0, -.01])
				cylinder(h=top_height + .02, r1=middle_radius-thickness, r2=top_radius-thickness);
			// bottom inside cone
			translate([0, 0, -bottom_height - .01])
				cylinder(h=bottom_height + .02, r1=bottom_radius-thickness, r2=middle_radius-thickness);
			// flute cutouts
			flutes(0);
		}
	}

	// add flutes
	intersection() {
		union() {
			// top cone
			cylinder(r1=middle_radius, r2=top_radius, h=top_height);
			// bottom cone
			translate([0, 0, -bottom_height])
				cylinder(r1=bottom_radius, r2=middle_radius, h=bottom_height);
		}
		flutes(flute_radius);
	}

}

funnel();

```


[User]
Okay, I'm looking to create a stencil and a matching "imprint" model using OpenSCAD, and I need it to be parametric so I can customize the text, font, size, and a few other things.

I'd like to be able to choose between seeing just the stencil, just the imprint, or both at the same time. There should also be a debug mode that prints all the parameters used.

Here's what I'm thinking:

*   **Text:** This should be a customizable string of text.
*   **Font:** I need to be able to select from a list of available fonts. I know that the Makerbot Customizer, which I intend to use for this, has some limitations. I would like to select from: Helvetica, Ubuntu, Butterfly Kids, Allerta Stencil, Stardos Stencil, Saira Stencil One, Sirin Stencil, Big Shoulders Stencil Text, and Big Shoulders Stencil Display.
*   **Text Size:** The size of the text should be adjustable.
*   **Extrusion Height:** I need to control the height of both the stencil and the imprint.
*   **Tolerance for Fitting:** There should be a tolerance setting that controls how much larger the stencil is than the imprint, to allow for a snug fit between them.
*   **Circle/Curve Approximation:** I want to be able to adjust the fineness of the approximation of circles and curves when rendering the text.
*   **Part Selection:** I need to be able to switch between showing just the imprint, just the stencil, or both.
*   **Debug Mode:** A debug mode that displays the values of all variables would be helpful.

Could you generate the necessary OpenSCAD files to do this, keeping in mind that the Customizer version is somewhat older and that special characters in comments might cause problems? I don't believe I will need any external libraries.

[Assistant]
Pochoir-v1-PPAC.scad:
```
/*
https://www.thingiverse.com/thing:6558241
https://www.lesimprimantes3d.fr/forum/topic/56857-qidi-slicer/#comment-587014
*/

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

/* [Global] */

// Which one would you like to see?
part = "les_deux_model"; // [ model_empriente: Juste le model_empriente, model_pochoire:Juste le model_pochoir, les_deux_model:Les deux, mode_var_debug]

/* [Paramasss] */
// Finesse de l'aproximation des cercles et courbes
my_fn=32;//[32:4:128]

texte = "Test";

// voir la limitation des font dispo dans le customiser
police = "Saira Stencil One";
/*
https://customizer.makerbot.com/docs#limitations

The text() function supports all the fonts from Google as well as some basic fonts such as Helvetica

// a la date de leur "build" donc probablement en 2015.

https://fonts.google.com/

# OK :
Helvetica
Ubuntu
Butterfly Kids

## https://fonts.google.com/?query=stencil
Allerta Stencil
Stardos Stencil
Saira Stencil One
Sirin Stencil
Big Shoulders Stencil Text
Big Shoulders Stencil Display

# KO :
Noto Sans Korean
Workbench
Noto Sans Old South Arabian

*/
taille_police=36;// [ 0 : 0.1 : 250 ]
haut_extrusion=4; // [ 0 : 0.1 : 100 ]

//
tolerance_emboitement=0.35;// [ 0.00 : 0.01 : 0.8 ]

/* [Hidden] */

vec_for_debug_var = [
    ["Version OpenSCAD", version()]
    ,["part", part]
    ,["my_fn", my_fn]
    ,["texte", texte]
    ,["police", police]
    ,["taille_police", taille_police]
    ,["haut_extrusion", haut_extrusion]
    ,["tolerance_emboitement", tolerance_emboitement]
//    ,["", ]
//    ,["", ]
];

print_part();

module print_part() {
	if (part == "model_empriente") {
		model_empriente(-tolerance_emboitement/2,haut_extrusion);
	        %model_pochoire(haut_extrusion);

	} else 	if (part == "model_pochoire") {
		%model_empriente(-tolerance_emboitement/2,haut_extrusion);
	        model_pochoire(haut_extrusion);
	} else 	if (part == "les_deux_model") {
		union(){
			model_empriente(-tolerance_emboitement/2,haut_extrusion);
	        	model_pochoire(haut_extrusion);
		}
	} else 	if (part == "mode_var_debug") {
    linear_extrude(height=1)
        mode_var_debug();
    } else {
		// WARN !
        decalage_gauche=10;
        color("red")
       union(){
	     	sphere(haut_extrusion);
               linear_extrude(height=5)
           translate([ decalage_gauche , 0 , 0])

           text(text=str("TODO ! add a : else if ( part == \"" ,part, "\" ) { ... } "));
           }
           linear_extrude(height=5)
           mode_var_debug();
	}
}

module mode_var_debug(){
	decalage_gauche=10;
	hauteur_ligne=14;
	union (){
		translate([decalage_gauche,len(vec_for_debug_var)*hauteur_ligne,0])
		for ( pos = [ 0: len(vec_for_debug_var)-1 ]){
			translate([0,-pos*hauteur_ligne,0])
			text(text=str(vec_for_debug_var[pos][0]," = ",vec_for_debug_var[pos][1]));
		}
	}
}

module 2d_empriente(){
    text(text=texte, font=police, size=taille_police, halign="center", valign="center",$fn=my_fn);

}

module model_empriente(un_offset=0,forced_haut_extrusion){
    //hauteur_extrusion_a_utiliser_localement
    h=is_undef(forced_haut_extrusion)?haut_extrusion:forced_haut_extrusion;
    translate([0,0,0])
    linear_extrude(height = h){
        offset(r=un_offset, chamfer=true)
        2d_empriente();
    }
}

module model_pochoire(forced_haut_extrusion){
    // une bidouille pour avoir beau rendue
    epsilon=0.002;
    //hauteur_extrusion_a_utiliser_localement
    h=is_undef(forced_haut_extrusion)?haut_extrusion:forced_haut_extrusion;
    difference(){
        translate([0,0,(h+epsilon)/2])
        cube([5*taille_police,3*taille_police,h], center=true);
        model_empriente(tolerance_emboitement/2,h+epsilon);
    }
}

```


[User]
Hey, I'm trying to design a blank to fill in some unused switch holes in my car's dashboard. I have an existing SCAD file that works, but it's kind of messy and I'd like a cleaner, more parametric solution. I need to be able to customize the size, corner radius, and wall thickness, plus add retaining clips.

Here are the specific things I need:

*   **Basic Shape:** A rounded cubeoid. It needs to be hollow to save material.
*   **Parameters:** I want to define:
    *   `blank_width` (the width of the blank)
    *   `blank_length` (the length of the blank)
    *   `blank_depth` (the depth of the blank)
    *   `blank_corner_radius` (the radius of the rounded corners)
    *   `blank_wall_thickness` (the thickness of the walls)
    *    `blank_clip_thickness` (the thickness of the retaining clips)
    *   `blank_clip_width` (the width of the retaining clips)
    *   `blank_clip_depth` (the depth of the retaining clips)
    *   `clips_x` (the number of clips on the width sides)
    *   `clips_y` (the number of clips on the length sides)
    *   `hollow` (a boolean to make it hollow)
     *    `tol` (a small tolerance value for the internal hollow portion)
*   **Clips:** The retaining clips should be positioned along the edges of the blank. I should be able to specify how many clips I want on the left/right (clips_x) and top/bottom (clips_y).  The clips need a "doohickey" on the end to help them retain, that is a scaled trapezoidal extrusion from the clip tip.
*   **Clean Code:** I'd really like a well-organized, easily understandable file. I am not using any libraries right now but would be okay with using a common one.
*   **Orientation:** The recommended print orientation for the clips is on the side, to maximize clip strength and minimize supports.

Could you generate the necessary parametric OpenSCAD files for me to do this?  Thanks!

[Assistant]
auto_switch_blank_2.scad:
```
blank_width = 32;
blank_length = 21;
blank_depth = 10;
blank_corner_radius = 2.5;
blank_wall_thickness = 1.5;
blank_clip_thickness = 2.5;
blank_clip_width = 6;
blank_clip_depth = 18;
hollow = true;
clips_x = 2;
clips_y = 1;
tol = 0.01;
$fn = 32;

module roundedCubeoid(blank_width, blank_length, blank_depth, blank_corner_radius) {
    // Define the points for the corners of the width-length face
    points = [
        [blank_corner_radius, blank_corner_radius, blank_depth/2],
        [blank_width - blank_corner_radius, blank_corner_radius, blank_depth/2],
        [blank_corner_radius, blank_length - blank_corner_radius, blank_depth/2],
        [blank_width - blank_corner_radius, blank_length - blank_corner_radius, blank_depth/2]
    ];

    // hull some cylinders to make a rounded cubeoid
    hull() {
        for (p = points) {
            translate(p) cylinder(r=blank_corner_radius, h=blank_depth, center=true);
        }
    }
}

module clipCutout(x_pos, y_pos, blank_clip_width, blank_clip_thickness, blank_wall_thickness) {
    translate([x_pos - blank_wall_thickness/2, y_pos - blank_wall_thickness/2, blank_wall_thickness])
    cube([blank_clip_width + blank_wall_thickness, blank_clip_thickness + blank_wall_thickness, blank_clip_depth]);
}

module addClip(x_pos, y_pos, blank_clip_width, blank_clip_depth, blank_clip_thickness, blank_wall_thickness) {
    // Add the clip
    translate([x_pos, y_pos, 0])
    cube([blank_clip_width, blank_clip_thickness, blank_clip_depth]);

    // Calculate the dimensions for the doohickey
    trapezoid_height = blank_wall_thickness / 2;
    extrude_scale = 1.3;

    // Add the doohickey at the end of the clip
    translate([x_pos, y_pos, blank_clip_depth]) {
        translate([blank_clip_width/2, blank_clip_thickness/2, 0])
        linear_extrude(height=trapezoid_height, scale=extrude_scale) {
            square([blank_clip_width, blank_clip_thickness], center=true);
        }

        translate([0, 0, trapezoid_height])
        translate([blank_clip_width/2, blank_clip_thickness/2, 0])
        linear_extrude(height=blank_wall_thickness, scale=1/extrude_scale) {
            square([blank_clip_width*extrude_scale, blank_clip_thickness*extrude_scale], center=true);
        }
    }
}

module blank(blank_width, blank_length, blank_depth, blank_corner_radius, blank_wall_thickness, blank_clip_thickness, blank_clip_width, blank_clip_depth, hollow, clips_x, clips_y, tol) {
    difference() {
        roundedCubeoid(blank_width, blank_length, blank_depth, blank_corner_radius);

        if (hollow) {
            translate([blank_wall_thickness, blank_wall_thickness, blank_wall_thickness+tol])
            roundedCubeoid(blank_width - blank_wall_thickness * 2, blank_length - blank_wall_thickness * 2, blank_depth - blank_wall_thickness, blank_corner_radius);
        }

        // Courtyard cutout for clips
        if(clips_x != 0) {
            for (i = [0:clips_x-1]) {
                x_pos = (blank_width) / (clips_x + 1) * (i+1) - blank_clip_width/2;
                y_pos = (blank_length - blank_clip_thickness);
                clipCutout(x_pos, 0, blank_clip_width, blank_clip_thickness, blank_wall_thickness);
                clipCutout(x_pos, y_pos, blank_clip_width, blank_clip_thickness, blank_wall_thickness);
            }
        }

        if(clips_y != 0) {
            for (j = [0:clips_y-1]) {
                x_pos = (blank_width - blank_clip_thickness);
                y_pos = (blank_length) / (clips_y + 1) * (j + 1) - blank_clip_width/2;
                clipCutout(0, y_pos, blank_clip_thickness, blank_clip_width, blank_wall_thickness);
                clipCutout(x_pos, y_pos, blank_clip_thickness, blank_clip_width, blank_wall_thickness);
            }
        }
    }

    // Clips themselves
    if(clips_x != 0) {
        for (i = [0:clips_x-1]) {
            x_pos = (blank_width) / (clips_x + 1) * (i+1) - blank_clip_width/2;
            y_pos = (blank_length - blank_clip_thickness);
            addClip(x_pos, 0, blank_clip_width, blank_clip_depth, blank_clip_thickness, blank_wall_thickness);
            addClip(x_pos, y_pos, blank_clip_width, blank_clip_depth, blank_clip_thickness, blank_wall_thickness);
        }
    }

    if(clips_y != 0) {
        for (j = [0:clips_y-1]) {
            x_pos = (blank_width - blank_clip_thickness);
            y_pos = (blank_length) / (clips_y + 1) * (j + 1) - blank_clip_width/2;
            addClip(0, y_pos, blank_clip_thickness, blank_clip_depth, blank_clip_width, blank_wall_thickness);
            addClip(x_pos, y_pos, blank_clip_thickness, blank_clip_depth, blank_clip_width, blank_wall_thickness);
        }
    }
}

// Example usage
blank(blank_width, blank_length, blank_depth, blank_corner_radius, blank_wall_thickness, blank_clip_thickness, blank_clip_width, blank_clip_depth, hollow, clips_x, clips_y, tol);

```


[User]
I'd like to design a parametric screwdriver holder for a Honeycomb Storage Wall (HSW) system. I've seen a few designs out there, but I need something that can adapt to different sized screwdrivers.

Here are the key features I'm looking for:

*   **Parametric Design:** The holder needs to be fully parametric so I can easily adjust the size of the slots to fit various screwdrivers without having to manually tweak the design.
*   **Individual Slots:** It should have multiple individual slots, each designed to hold a single screwdriver. I need to specify the shaft diameter and handle diameter for each slot, and the design should automatically accommodate them with proper clearance.
*   **HSW Compatibility:** The base of the holder should include mounting holes that are compatible with the standard HSW grid system. I'm using M3 screws, but it would be great if I could easily change that to M4 or M5. I'm not sure what screw head type to use, but something like ISO 14581 would be fine as a default.
*   **Rounded Edges:** I'd like the edges of the holder and the slots to have a nice rounded fillet for a more polished look and to improve usability.
*   **Adjustable Arm Spacing:** I need to be able to control the vertical spacing between the arms that hold each screwdriver, so that I can accommodate different sizes.

Essentially, I want to define an array of screwdriver handle and shaft sizes, and the code should generate a holder with the correct slots for those screwdrivers, while ensuring it mounts to my HSW. I'd also like to be able to easily change the overall size of the holder as well as the screw type.

I'd like the file to use the `openscad-screw-holes/screw_holes.scad` library, since I'm already used to using that for screw holes.

I would like you to generate one or more `.scad` files, as you feel is necessary.

[Assistant]
parametric-screwdriver-holder-for-hsw.scad:
```
/*
Parametric screwdriver holder for HSW

Copyright 2024 nomike[AT]nomike[DOT]com

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.

2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS” AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

include<openscad-screw-holes/screw_holes.scad>;

$fn=32;
arm_y_distance = 25;
plate_z = 2;
plate_rounding = 7;
arm_rounding = 2;

screw_driver_handle_padding = 3;
arm_thickness = 3;
arm_offset = 0;
plate_y = arm_y_distance + arm_thickness *2;
plate_padding_x = 3;
plate_padding_y = 5;

main_outer_side = 12.99;
grid_spacing = 40.88;
screw_m = M3;
screw_type = ISO14581;

// [<shaft_width>, <handle_width>]
arms = [
    [3.5, 14],
    [7.5, 18],
    [7.5, 18],
    [7.5, 18],
    [11, 39.8]
];

// calculate arm_length
lengths = [for (arm = arms) each arm[1]];
arm_length = max(lengths) + screw_driver_handle_padding;

// calculate arm width
function sum_arm_widths(arms, i=0) = i>=len(arms) ? 0 : (arms[i][1]) + sum_arm_widths(arms, i+1);

_plate_x = sum_arm_widths(arms);
//- arms[len(arms) -1][1] + arms[len(arms) -1][0] + 2 * arm_thickness + 2 * arm_thickness;
screw_hole_distance_units = floor((_plate_x - 10 + plate_padding_x * 2)/ grid_spacing);
screw_hole_spacing = grid_spacing * screw_hole_distance_units;

module rounded_cube(size, r, double_sided = true) {
    translate([r, r, 0]) hull() {
        if(double_sided) {
            translate([0, 0, 0]) cylinder(r=r, h=size[2]);
        } else {
            translate([-r, -r, 0]) cube([size[0], r, size[2]]);
        }
        translate([size[0] - r * 2, 0, 0]) cylinder(r=r, h=size[2]);
        translate([0, size[1] - r * 2, 0]) cylinder(r=r, h=size[2]);
        translate([size[0] - r * 2, size[1] - r * 2, 0]) cylinder(r=r, h=size[2]);
    }
}

module draw_fillet(arms, idx) {
    arm_width = arms[idx][0] + 2 * arm_thickness;
    difference() {
        union() {
            // +y fillet
            translate([-3, 3, 0]) rotate([90, 0, 0]) difference() {
                cube([arm_width + 6, 3, arm_thickness]);
            }
            // -y fillet
            translate([-3, -3, 0]) rotate([90, 0, 0]) difference() {
                cube([arm_width + 6, 3, arm_thickness]);
            }

            // +x fillet
            translate([-3, - 3, 0]) rotate([0, 0, 0]) difference() {
                translate([0, -3, 0]) cube([3, arm_thickness + 6, arm_thickness]);
            }
            //-x fillet
            translate([arm_width, -3, 0]) rotate([0, 0, 0]) difference() {
                translate([0, -3, 0]) cube([3, arm_thickness + 6, arm_thickness]);
            }
        }
        union() {
            // +y fillet
            translate([-3, 3, 0]) rotate([90, 0, 0]) difference() {
                translate([0, 3, 0]) rotate([0, 90, 0]) cylinder(r=3, h=arm_width + 6);
            }
            // -y fillet
            translate([-3, -3, 0]) rotate([90, 0, 0]) difference() {
                translate([0, 3, 3]) rotate([0, 90, 0]) cylinder(r=3, h=arm_width + 6);
            }

            // +x fillet
            translate([-3, -3, 0]) rotate([0, 0, 0]) difference() {
                translate([0, 6, 3]) rotate([90, 0, 0]) cylinder(r=3, h=arm_thickness + 6);
            }
            //-x fillet
            translate([arm_width, -3, 0]) rotate([0, 0, 0]) difference() {
                translate([3, 6, 3]) rotate([90, 0, 0]) cylinder(r=3, h=arm_thickness + 6);
            }
        }
    }
}

module draw_arm(arms, idx) {
        arm_width = arms[idx][0] + 2 * arm_thickness;
        rotate([90, 0, 0]) difference() {
            rounded_cube([arm_width, arm_length, arm_thickness], arm_rounding, double_sided=false);
            translate([arm_width / 2, arm_length - (arm_width / 4) - (arms[idx][0] / 2), 0]) cylinder(d=arms[idx][0], h=20);
        }
        draw_fillet(arms, idx);
}

module draw_arms(arms, idx=0) {
    if (idx < len(arms)) {
        arm_width = arms[idx][0] + 2 * arm_thickness;
        translate([(arms[idx][1] / 2)- (arm_width / 2), 0, 0]) union() {
            // top arm
            translate([0, arm_thickness + arm_offset, 0]) draw_arm(arms, idx);
            // bottom arm
            translate([0, plate_y - arm_offset, 0]) draw_arm(arms, idx);
        }
        translate([arms[idx][1], 0, 0])
        draw_arms(arms, idx + 1);
    }
//        if(idx + 1 == len(arms)) {
//            translate([(arms[idx][1]) / 2, 0, 0])  difference() {
//                draw_arms(arms, idx + 1);
//            }
//        } else {
//            translate([(arms[idx][1]), 0, 0])  difference() {
//                draw_arms(arms, idx + 1);
//            }
//        }
//    }
}

module bbox() {

    // a 3D approx. of the children projection on X axis
    module xProjection()
        translate([0,1/2,-1/2])
            linear_extrude(1)
                hull()
                    projection()
                        rotate([90,0,0])
                            linear_extrude(1)
                                projection() children();

    // a bounding box with an offset of 1 in all axis
    module bbx()
        minkowski() {
            xProjection() children(); // x axis
            rotate(-90)               // y axis
                xProjection() rotate(90) children();
            rotate([0,-90,0])         // z axis
                xProjection() rotate([0,90,0]) children();
        }

    // offset children() (a cube) by -1 in all axis
    module shrink()
        intersection() {
            translate([ 1, 1, 1]) children();
            translate([-1,-1,-1]) children();
        }

    shrink() bbx() children();
}

// arms
translate([0, 0, plate_z]) draw_arms(arms);

// base plate
difference() {
    translate([0 - plate_padding_x, 0 - plate_padding_y, 0]) rounded_cube([_plate_x + plate_padding_x * 2 , plate_y + plate_padding_y * 2, plate_z], plate_rounding);

    // screw holes
    translate([((_plate_x - screw_hole_spacing) / 2), plate_y / 2, plate_z]) rotate([180, 0, 0]) screw_hole(screw_type, screw_m, plate_z);
    translate([ + ((_plate_x - screw_hole_spacing) / 2) + screw_hole_spacing, plate_y / 2, plate_z]) rotate([180, 0, 0]) screw_hole(screw_type, screw_m, plate_z);
}

// module screw_holes(count=20) {
//     if(count > 0) {
//         color("blue") cylinder(d=3, h=10);
//         translate([grid_spacing, 0, 0]) screw_holes(count - 1);
//     }
// }

// intersection() {
//     translate([0, plate_y / 2, 0]) screw_holes();
//     bbox() draw_arms(arms);
// }
```


[User]
Hey, I'm looking to design a wall bracket that can hold a small device, like a wifi router, without needing to drill into the wall. I've seen some designs that use adhesive strips, which is what I'd like to achieve.

The basic design idea I have is that of a simple bracket with a vertical arm, a horizontal base, and a support piece, basically an upside-down "L" shape with an extra bracing cylinder. I want to make this parametric so I can adjust it for different sized devices. It should have a flat base for an adhesive strip.

Here are the features that I need to control:

*   **Device Space:** The width of the space where the device sits.
*   **Bracket Width:** The width of the material used for the bracket.
*   **Bracket Height:** The height of the vertical arm.
*   **Base Thickness:** The thickness of the bracket's base.
*   **Rounded Edges:** An option to have rounded edges on the bracket.
*   **Mounting Area:** The width and thickness of the flat section meant to attach to the wall. This will also need to be adjustable, and should be connected to the horizontal base of the L.
*   **Support Cylinder Radius:** Radius of the cylindrical support.

I need the design to be easily customized, so I'm hoping for a parametric OpenSCAD design using modules. It doesn't need to be overly complex; the simple shape would be great.

I'd like you to generate the necessary .scad files for this design. No external libraries are needed. Let me know if you have any questions.

[Assistant]
wall-bracket.scad:
```
// Tamanho do espaço para caber o objeto
esp = 50;
// Largura do suporte
larg = 8;
// Se o suporte deve ser arredondado nas bordas
rounded = true;
// Altura do suporte
altsup = 35;

$fn = 60;

module suporte() {
    // Braço da frente
    color("red")
    translate([0, 0, larg])
        cube([larg, larg, altsup]);
    // Área para parafusar
    color("yellow")
    translate([0, esp+larg, -(altsup)/2])
        cube([larg*2, 3, altsup+larg*2]);
    color("brown")
    // Haste
    cube([larg, esp + larg, larg]);
    // Reforço
    translate([larg/2, esp+larg, 0])
        rotate([90, 0, 0])
        cylinder(h=esp+larg, r1=larg/2, r2=larg/2);
}

if (rounded) {
    minkowski() {
        suporte();
        sphere(1);
    }
} else {
    suporte();
}
```


[User]
Okay, I'm looking to create a tool for setting the cable length on a Shimano roller brake, specifically the kind used on some e-bikes. I've seen a design online, but it doesn't have all the features I need. I'm hoping you can help me generate the OpenSCAD code for a parametric version.

The tool needs to be essentially a base with two channels, one for the front brake cable and one for the rear. These channels will have a cylindrical section that has an offset to create the correct cable length. The basic idea is that you place the brake cable into the channel and then can hold it at the proper length, allowing for easy adjustment.

Here's a more detailed breakdown of what I want:

**Overall Structure:**

*   The main body of the tool will be a shaped piece, kind of like a rounded rectangle, but with a specific profile. The outline is generally rectangular, but the corners will be rounded.
*   There will be two channels, one each for the front and rear brake cables, running along the length of the tool. These channels need to be circular and of a specific diameter and length, with one end having an adjuster (which is a short cylinder with a different radius along with an extended cylindrical part).
*   The tool will need to be parametric for the length of the front and rear cable.

**Specifics:**

*   **Base Shape:** I've got some reference measurements, but basically I want a rectangle with some rounded corners made using minkowski on a polygon. The corners will be based on two radii for the minkowski. The base needs to be a defined thickness. I am going to need to be able to control the overall length of the tool and the position of the channels. The base will be a solid piece, and I want to be able to cut out a section that will accept the metal plate from the original Shimano tool. I would also like to be able to make a version of the tool that does not have the recess, in case the user does not have the original tool. And of course the user should be able to generate just the metal plate.
*   **Cable Channels:**  Each channel should start with a circular cut in the main body. Then there will be an adjuster that has a larger radius along its face with a smaller radius extending from this face.  These adjusters will be positioned a defined distance from the end of the channels and have a specific length. The length of these channels should be automatically determined by the cable length parameters.
*   **Cable Length Parameters:** I need to be able to specify the length of both the front and rear brake cables. These should be used to calculate the exact position of the channels and the length of their extensions as well as the position of the adjuster.
*   **Text Labels:** The tool should have text labels to indicate which channel is for the front brake and which is for the rear. The text should also display the cable lengths.
*   **Plate:** The metal plate is rectangular, with rounded ends. There is a small cutout on the front with the circular hole offset from the center. There should be holes for screws, as well as a wrench-like cutout in the ends.
*   **Units:** All measurements should be in millimeters.

**Parametric Considerations:**

*   `length_f`: Length of the front brake cable in millimeters.
*   `length_r`: Length of the rear brake cable in millimeters.
*   `part`: A string parameter for whether to generate the full tool with the plate cutout ("a"), the tool without the plate cutout ("b"), or just the plate ("c").
*   Other parameters such as radii, base thickness, etc, can be defined and controlled.

**Libraries**
I believe that all of this can be done using standard OpenSCAD, so no external libraries will be required.

The whole idea is to make a tool that is adjustable based on the brake cable length. I would like it to be robust for 3D printing, but also accurate. I'd be very grateful if you could generate the necessary OpenSCAD code for this.

[Assistant]
tool.scad:
```
//Roller brake tool by Jacob Jones

//Front brake cable length
length_f = 101; // [80:120]

//Rear brake cable length
length_r = 99; // [80:120]

//Which part?
part = "a"; // [a:Tool with plate recess, b:Plastic only tool, c:Plate for tool]

/* [Hidden] */

$fs = $preview ? 2.5 : .5;
$fa = $preview ? 5 : 1;

overlap = .1;

radius_1 = 8;
radius_2 = 4;

base_thickness = 13;

Print_Part();

module Base_Solid(){

    module Base_Outline(){
        outline = [
            [-(23 - (radius_1+radius_2)), -(23 - (radius_1+radius_2))],
            [(23 - (radius_1+radius_2)), -(23 - (radius_1+radius_2))],
            [(20 - (radius_1+radius_2)), (length_f - 2 + 30 - (radius_1+radius_2))],
            [-(20 - (radius_1+radius_2)), (length_r - 2 + 30 - (radius_1+radius_2))]
        ];
        minkowski(){
            difference(){
                polygon(outline);
                translate([15,length_f/2+10,0])resize([20,length_f + 40])circle(d = 20, $fn = 32);
                translate([-15,length_r/2+10,0])resize([20,length_r + 40])circle(d = 20, $fn = 32);
            }
            circle(r = radius_1, $fn = 32);
        }
    }

    module Base_Cut(){
        cut = [
            [(22 + overlap), (length_f - 7)],
            [-(22 + overlap), (length_r - 7)],
            [-(22 + overlap), (length_r + 50)],
            [(22 + overlap), (length_f + 50)],
        ];
        linear_extrude(height = base_thickness-4.5)
            difference(){
                translate([0,.5,0]) resize([40,length_f + 54])
                Base_Outline();
                polygon(cut);
            }
    }

    translate([0,0,-base_thickness]) difference(){
        translate([0,0,radius_2]) minkowski(){
            linear_extrude(height = base_thickness - radius_2*2) Base_Outline();
            sphere(r = radius_2, $fn=32);
        }
        translate([0,0,-overlap]) Base_Cut();
    }

}

module Adjuster(){
    union(){
        translate([0, 19 - 5, - 12.5]){
            cylinder(h = 17.5, r = 5.25);
        }
        rotate([-90,0,0]) {
            cylinder(h = 19 + overlap, r = 3);
            translate([0,0,17]){
                cylinder (h = 100, r = 6);
            }
        }
    }
}

module Channels() {
    translate([38.75/2-19/2,0,0]){
        translate([0,length_f - 2,0]) Adjuster();
        translate([0,-(30 + overlap),0])
           rotate([-90,0,0])
            cylinder(h = length_f + 30, r = 2);
        }
        translate([-(38.75/2-19/2),0,0]){
        translate([0,length_r - 2,0]) Adjuster();
        translate([0,-(30 + overlap),0])
           rotate([-90,0,0])
            cylinder(h = length_r + 30, r = 2);
        }
}

module Text() {
    translate([3,length_f/2,-.4])
            linear_extrude(height = 4)
                rotate([0,0,-90])
                    text(str("FRONT ", length_f, "mm"), size = 4, halign = "center");

        translate([-3,length_r/2,-.4])
            linear_extrude(height = 4)
                rotate([0,0,90])
                    text(str("REAR ", length_r, "mm"), size = 4, halign = "center");
}

module Plate_Outline(){
    width = 38.75;
    height = 19;
    thickness = 3;
    module PlateHalf(){
        translate([width/2-height/2,0,0]){
            cylinder(h = thickness + overlap,r = height/2, center = true);
        }
    }
    translate([0,-height/2, -thickness/2 + overlap]) union() {
        hull(){
            PlateHalf();
            mirror([1,0,0]) PlateHalf();
        }
        translate([-(width/2-15.5), height/2-3.5, 0]){
            cylinder(h = thickness + overlap, r = 5, center = true);
        }
    }
}

module Screw_Hole(){
    translate([0,-19/2,0])
    cylinder(h = 2*base_thickness, r=2.5, center = true);
}

module Wrench(){
    height = 3 + overlap * 3;
    module Hole(){
        translate([9.875,-19/2,0])
        rotate([0,0,30])
        difference(){
            translate([0,0,-height + 2*overlap])
            cylinder(h = height, r = 6+overlap);
            translate([0,-(11+overlap),0])
            cube([12, 12, height * 2], center = true);
            translate([0,11+overlap,0])
            cube([12, 12, height * 2], center = true);
        }
    }
    Hole();
    mirror([1,0,0]) Hole();

}

module Plate(){
    module PlateHole(){
        translate([0,-19/2,0])
        cylinder(h = 9, d = 4.2, center = true);
    }
    difference() {
        Plate_Outline();
        Wrench();
        Screw_Hole();
    }

}

module Print_Part() {
    if (part == "a"){
        difference(){
            Base_Solid();
            Plate_Outline();
            Screw_Hole();
            Channels();
            Text();
        }
    } else if (part == "b"){
        difference(){
            Base_Solid();
            Wrench();
            Channels();
            Text();
        }
    } else if (part == "c"){
        Plate();
    }
}
```


[User]
I'm looking for an OpenSCAD design for a customizable rectangular cap, something like an end cap for a tube or LED profile. I need it to have rounded edges and be parametric so I can easily adjust the size and wall thickness.

Specifically, I need the following parameters to be adjustable:

*   **internal_Width:** The internal width of the cap, designed to fit over an object.
*   **internal_Depth:** The internal depth of the cap.
*  **internal_Height:** The internal height of the cap.
*   **wall_Thickness:** The thickness of the cap's walls.
*   **rounding_Radius:** The radius of the rounded corners.

I need the cap to have a flat top and an open bottom where the "tube" would enter, and the walls and top will all have equal wall thickness. The cap should fit *around* an object of the `internal_Width`, `internal_Depth`, and `internal_Height`.

Could you generate the OpenSCAD code for this?  I'd like the code to be as efficient and readable as possible. I'm not using any external libraries right now.

[Assistant]
Rounded_square_tube_cap.scad:
```
/* [Shell parameters] */
rounding_Radius = 2;
wall_Thickness = 2;

/* [Internal cube size] */
internal_Width = 17.7;
internal_Depth = 7.5;
internal_Height = 7.5;

/* [Hidden] */
$fn = 32;
delta = 0.01;//to get rid of artifacts on preview

difference()
{
    rounded_cube(width = internal_Width + 2 * wall_Thickness,
                depth = internal_Depth + 2 * wall_Thickness,
                height = internal_Height + wall_Thickness,
            rounding_Radius = rounding_Radius);

    translate([0, 0, internal_Height * 0.5 - delta - wall_Thickness])
        cube([internal_Width, internal_Depth, internal_Height + delta], center = true);
}

module rounded_cube(width, depth, height, rounding_Radius)
{
    half_width = width * 0.5;
    half_depth = depth * 0.5;
    half_height = height * 0.5;

    //TODO it should be centered optionaly with a parameter
    translate([0, 0, half_height])
    hull()
    {
        for (x = [-half_width + rounding_Radius, half_width - rounding_Radius])
        {
            for (y = [-half_depth + rounding_Radius, half_depth - rounding_Radius])
            {
                translate([x, y, half_height - rounding_Radius])
                    sphere(r = rounding_Radius);

                translate([x, y, -half_height])
                    cylinder(r = rounding_Radius);
            }
        }
    }
}
```


[User]
I'd like to have an OpenSCAD design for a reloading tray, but with a few specific features that I'm hoping you can help with.

First, I need the tray to hold a variable number of reloading cases arranged in a honeycomb pattern. I'm thinking the arrangement would be defined by the number of rows and the number of cells per row. The cells themselves should have a specific diameter and spacing from each other. There needs to be a chamfer at the top of each cell.  Also, I need a small hole in the bottom of each cell. I'd like the overall height of the tray and the depth of the cell holes and chamfers to also be customizable.

Second, I want a label area on each of the two longer sides of the tray. This should be an inset region with rounded corners and a chamfer around its inner edge. The label text itself should be able to be customized as well, including size and font. The label region should extend down into the side of the tray and be of a specific thickness.

Finally, I'd like a chamfered edge around the entire tray, both top and bottom, with a variable distance for the chamfer. The overall dimensions of the tray should be calculated based on the number of rows and cells per row, along with some margins around the outermost cells. The corners of the tray itself should be rounded as well.  I also want the tray to have a specified bottom thickness.

It would be great if you could generate an OpenSCAD file (or files, whatever makes sense) that uses parameters to control all of these features. I'm hoping to be able to set things like the case diameter and spacing, number of rows and cells per row, the label text and size, chamfer distances and rounding radii, and tray dimensions.  I would like to generate a model using mm, rather than the 'thou' units that I see in many other designs.

I'm not looking to use any external libraries in this design.  Could you do that?

[Assistant]
HoneycombReloadingTray.scad:
```
/**************************************************************************
   Reloading Tray (c) 2024 by Wayne E Wright,
   https://www.thingiverse.com/wwrr55
   is licensed under Attribution-ShareAlike 4.0 International. To view a
   copy of this license, visit
   http://creativecommons.org/licenses/by-sa/4.0/
*****************************************************************************/

echo ("HoneycombReloadingTray.scad version 1.3");

/*
** Version 1.3  October, 2024
**   45AR needs slightly larger hole
** Version 1.2  July, 2024
**   Add 38 Spl, 357 Mag
** Version 1.1  May, 2024
**   Add 45 Auto Rim
*/

/* [ALL DIMENSIONS IN THOU] */
AllDimensionsInThou = 0; //[0:thou]]
StlExportIsMM = 0; //[0:mm]]
/* [Hidden] */
PresetThatIsManual = 4;
/* [Cartridge] */
// Other than Manual ignores remaining settings in this Cartridge tab
Preset=1; // [0: 38spl/357mag, 1:44spl/44mag/45Colt, 2:45ACP, 3:45AR, 4:Manual]
TrayHeight = 875;
CaseHoleDiameter = 525;
CaseHoleSpacing = 825;
SideLabelText = "3X";

/* [Capacity] */
NumRows = 5;
NumCellsPerRow = 10;

/* [Tray] */
SideLabelDepth = 30;
SideLabelTextSize = 350;
LabelFont = "Arial";

// Box extent beyond last cartridge left/right
TrayXMargin = 115;
// Box extent beyond last cartridge front/back
TrayYMargin = 115;
TrayEdgeRoundRadius = 500;
TrayBottomThickness = 62;
TrayTopBottomChamferDistance = 62;
CellChamferOffsetDiameter = 80;
CellBottomHoleDiameterOffset = 200;

InsetDepth = 50;
InsetMargin = 150;
InsetRoundingRadius = 100;
InsetChamferDistance = 70;

module __Customizer_Limit__ () {}  //below here does not appear in Customizer

// $preview built-in
$fa = $preview ? 12 : 4;
$fs = $preview ? 2 : 1;

RadiusToWidthScale = 1/sqrt(3);
HoneyCombAngle = 60;

//                            [0: 38spl/357mag, 1:44spl/44mag/45Colt,      2:45ACP,          3:45AR, 4:Manual]
PresetTrayHeights =           [790,                 813    ,                   600,             600,];
PresetCaseHoleDiameters =     [457,                 525   ,                    495,             536,];
PresetCaseHoleSpacings =      [719,                 825   ,                    790,             826,];
PresetLabels =                ["38 Spl, 357 Mag", "44 Spl, 44 Mag, 45 Colt", "45 ACP",     "45 Auto Rim"];

TrayHeight_ = Preset==PresetThatIsManual ? TrayHeight-TrayBottomThickness : PresetTrayHeights[Preset];
CaseHoleDiameter_ = Preset==PresetThatIsManual ? CaseHoleDiameter : PresetCaseHoleDiameters[Preset];
CaseHoleSpacing_ = Preset==PresetThatIsManual ? CaseHoleSpacing :   PresetCaseHoleSpacings[Preset];
SideLabelText_ = SideLabelText!= "3X" ? SideLabelText : (Preset==PresetThatIsManual ? SideLabelText : PresetLabels[Preset]);

TrayXWidth = (TrayXMargin * 2) + CaseHoleSpacing_ * (NumCellsPerRow + 1) - CaseHoleDiameter_/2;
TrayYDepth = (TrayYMargin * 2) + (CaseHoleSpacing_ * sin(HoneyCombAngle) * (NumRows-1) ) + CaseHoleDiameter_;

SideLabelTextSize_ = min(SideLabelTextSize, TrayHeight_ - 2 * (InsetMargin + InsetChamferDistance ));

CellBottomHoleDiameter_ = CaseHoleDiameter_ - CellBottomHoleDiameterOffset;

mmPerThou = 25.4 / 1000;

module CellRow(count, height)
{
    for (itor = [0:1:count-1] )
        translate([itor*CaseHoleSpacing_, 0, 0])
        {
            cylinder(h=height, d=CaseHoleDiameter_ );
            // chamfer each hole
            translate([0,0,height])
            {
                rotate([180,0,0])
                linear_extrude(height=CellChamferOffsetDiameter, scale=CaseHoleDiameter_ / (CaseHoleDiameter_ + CellChamferOffsetDiameter))
                    circle(d=CellChamferOffsetDiameter+CaseHoleDiameter_);
            }
            // hole in the bottom of each cell
            translate([0,0,-TrayBottomThickness - 2])
                cylinder(d=CellBottomHoleDiameter_, h=TrayBottomThickness + 3);
        }
}

module LayoutCells(numRows, rowLen, height)
{
    for (row = [0:2:numRows-1])
        translate([0, row * CaseHoleSpacing_ * sin(HoneyCombAngle)])
            CellRow(rowLen, height);
    translate // interior row
        (CaseHoleSpacing_ * [-cos(HoneyCombAngle), sin(HoneyCombAngle)])
        for (row = [1:2:numRows-1])
           translate([0, (row-1) *  CaseHoleSpacing_ * sin(HoneyCombAngle)])
               CellRow(rowLen+1, height);
}

module BoxFootprint()
{
    $fa = $fa * 1/5; // rounding circle is big. prints better with finer resolution
    offset(r= TrayEdgeRoundRadius)
    offset(r= -TrayEdgeRoundRadius)
    square([TrayXWidth, TrayYDepth]);
}

module SideLabel()
{
   translate([TrayXWidth/2, 1 + InsetDepth,   (TrayHeight_-TrayBottomThickness)/2])
        rotate([90,0,0])
        linear_extrude(height = SideLabelDepth)
            text(SideLabelText_, size=SideLabelTextSize_, font=LabelFont,
                            halign="center", valign="center");
}

// put side profile as 2D in x-y plane
sideProfile = [[0,0],[0,TrayHeight_ + TrayBottomThickness],
            [TrayXWidth-2*TrayEdgeRoundRadius,TrayHeight_ + TrayBottomThickness],
            [TrayXWidth-2*TrayEdgeRoundRadius,  0]];
sideProfileX = [for (i = [0:1:len(sideProfile)-1]) sideProfile[i][0]];
sideProfileY = [for (i = [0:1:len(sideProfile)-1]) sideProfile[i][1]];
sideProfileCenter = [max(sideProfileX), max(sideProfileY)] * 0.5;

module SideInset()
{
    pfmin = [min(sideProfileX), min(sideProfileY)];
    pfmax = [max(sideProfileX), max(sideProfileY)];
    diff = pfmax - pfmin;
    s = [(diff[0] - 2*(InsetChamferDistance + InsetMargin))/(diff[0]-2*InsetMargin),
        (diff[1] - 2*(InsetChamferDistance + InsetMargin))/(diff[1]-2*InsetMargin)];

    translate([TrayEdgeRoundRadius, -1, TrayHeight_])
    rotate([-90,0,0])
    translate(sideProfileCenter)
    {
        linear_extrude(height = InsetDepth, scale = s)
            offset(r = InsetRoundingRadius)
            offset(r = -InsetMargin-InsetRoundingRadius)
                translate(-sideProfileCenter)
                    polygon(sideProfile);
    }
}

module MainFootprintChamfer(thick)
{
    translate([0,0,-TrayBottomThickness-1])
    {
        difference()
        {
            linear_extrude(height = thick+2)
                    offset(r=thick)
                        BoxFootprint();
            translate([TrayXWidth/2,TrayYDepth/2,1])
                linear_extrude(height = thick+3, scale=[(2*thick+TrayXWidth)/TrayXWidth, (TrayYDepth + 2*thick)/TrayYDepth])
                    translate([-TrayXWidth/2,-TrayYDepth/2])
                    offset(r=-thick)
                        BoxFootprint();
        }
    }
}

module TrayBox() {
    color ([1, 1, .2])
    union (){
        difference()
        {
            union() {
                // base
                     translate([0,0,-TrayBottomThickness])
                        linear_extrude(height = TrayHeight_ + TrayBottomThickness)
                            BoxFootprint();

            }
            // here is where the ammo goes
            translate([0,0, 1])
                         translate([CaseHoleDiameter_/2 + cos(HoneyCombAngle) * CaseHoleSpacing_ + TrayXMargin ,
                            TrayYMargin + CaseHoleDiameter_/2])
                            LayoutCells(NumRows,NumCellsPerRow, TrayHeight_+1);

            SideInset();
            translate([TrayXWidth/2, 0, 0])
            rotate([0,0,180])
            translate([-TrayXWidth/2, -TrayYDepth, 0])
                    SideInset();

            // chamfer the base bottom
            MainFootprintChamfer(thick=TrayTopBottomChamferDistance);
            // and top
            translate([TrayXWidth/2,0,TrayHeight_-TrayBottomThickness])
            rotate([0,180,0])
                translate([-TrayXWidth/2,0,0])
                    MainFootprintChamfer(thick=TrayTopBottomChamferDistance);
        }
        if (SideLabelText != "")
        {
            SideLabel();
            translate([TrayXWidth/2, 0, 0])
            rotate([0,0,180])
            translate([-TrayXWidth/2, -TrayYDepth, 0])
                    SideLabel();
        }
   }
}

// Here begins the description of what to build and/or display now
scale(mmPerThou)
{
    TrayBox();
}

```