[User]
Hi, I'm looking for help creating a tool for quickly checking the thread size of plastic bottles. I have a basic script already, but it's not very flexible and I think a more parametric design would be much better. I'd like to be able to easily adjust parameters for different bottle sizes without directly editing the code.

The tool should consist of a series of interlocking threads that I can use to test a bottle's thread. I'll need to be able to specify the following:

*   **Thread pitch:** The distance between threads.
*   **Outer diameter:** The outer diameter of the bottle's thread.
*   **Thread depth:** The depth of the thread itself. I'd like to be able to adjust this independently of the pitch, if possible, since different bottles have different thread shapes.
*   **Number of threads:** How many threads should be included in the tool.

The design should generate a "comb" of teeth, each representing a portion of the threads, and a central cylinder representing the bottle. The threads should have the characteristic triangular shape (with two of the sides being of equal length) typical of plastic bottle threads, but the actual shape doesn't need to be perfect. I'm planning on using it to quickly find the proper pitch rather than to reproduce an exact thread for use as a functional thread. The threads should be oriented so that I can try to thread my bottle onto it, meaning that the thread comb should surround the central cylinder.

Also, I would really like if the file was set up to be easy to use. This means it would be nice if it used a `module` to create the tool, with the parameters as function arguments. I'd like all of this to be contained in a single OpenSCAD file. I don't want any dependencies on external libraries or modules.

[Assistant]
thread_tester_v2.scad:
```

//******* change this to fit to your bottle ***********
// Pitch of the bottle thread in mm
thread_pitch = 4;
// Outer diameter of bottle thread in mm
outer_d = 28.25;

//**************************************************

num = floor(outer_d/thread_pitch)+2;// number of teeth drawn.
pos = num*thread_pitch/2; //displacement of center of cylinder

delta = 0.05; //adjust for "zero walls"

difference() {
union(){
translate([0,-num*thread_pitch+delta,-1])cube([num*thread_pitch,num*thread_pitch,2]);
for (i=[0:num-1])
translate([i*thread_pitch,0,0])linear_extrude(height = 2, center = true, convexity = 10,  slices = 20,  $fn = 16)
 polygon(points=[[0,0],[thread_pitch,0],[thread_pitch*2/3,thread_pitch*2/3],[thread_pitch*1/3,thread_pitch*2/3]]);
}
//cylinder
 translate([pos,-pos,-1.5]) cylinder(d=outer_d,h=3,$fn=90);
}
```


[User]
Hey, I'm working on a project to add some adjustable feet to my keyboard case, and I've designed a little knob to go with it. I'm hoping you can help me create a parametric version using OpenSCAD.

Essentially, I need a cylindrical knob with a knurled grip and a recessed socket on the bottom to attach to a screw head. The current design is pretty specific to my M3 screws, but I'd love to make it easier to customize for different sizes.

Here are the basic dimensions and features I want to be adjustable:

*   **Knob Diameter:** The overall diameter of the knob.
*   **Knob Length:** The overall length of the knob.
*   **Socket Diameter:** The diameter of the recessed hole for the screw head.
*   **Socket Depth:** The depth of the recessed hole for the screw head.
*   **Knurling Offset:** The distance from the edge of the knob to the start of the knurling.
*   **Knurling Depth:** The depth of the knurled pattern.
*   **Knurl Count:** The number of knurls around the knob.
*  **Knurling Facets:** The number of facets that are used to build each individual knurl cylinder.

I'm currently using a rounded cylinder function I found online, and would love it if you could provide a parametric version of that for the main body of the knob. It would also be fantastic if the knurl pattern could be generated with the same function using the various parameters described above. I'm not tied to any specific OpenSCAD library, but if you happen to know a library that already provides the rounded cylinder function, I'm happy to use that instead. Please do not rely on any functions provided in my attached .scad file.

I'd like to be able to specify all of the dimensions above as variables at the start of the file, so they can be easily adjusted in OpenSCAD's customizer, or by editing the file directly.

The end goal is to have a single, parametric OpenSCAD file that generates the knurled knob with a screw socket. It will be really useful for me and others to have a design that can be easily tweaked to match different fasteners and use cases.

[Assistant]
knob.scad:
```
// Knob diameter
knob_diameter = 10;

// Knob length
knob_length = 7.5;

// Socket diameter
socket_diameter = 5.75;

// Socket depth
socket_depth = 3.1;

// Knurling offset
knurling_offset = 0.1;

// Knurling depth
knurling_depth = 1;

// Knurl count
knurl_count = 8;

// Knurling facets
knurling_facets = 20;

// Credit for the rounded_cylinder function goes to kevinfquinn.
// Copied from
// https://www.thingiverse.com/groups/openscad/forums/general/topic:17201
// on 2019-02-04.
module rounded_cylinder(r,h,n) {
  rotate_extrude(convexity=1) {
    offset(r=n) offset(delta=-n) square([r,h]);
    square([n,h]);
  }
}

difference() {
    kradius = knob_diameter / 2;
    rounded_cylinder(r=kradius, h=knob_length, n=2, $fn=60);
    kcircle_radius = kradius + knurling_offset;

    for(a=[0:360.0 / knurl_count:360]) {
        translate([kcircle_radius * cos(a), kcircle_radius * sin(a), 0]) {
            rounded_cylinder(h=knob_length, r=knurling_depth, n=1, $fn=knurling_facets);
        }
    }
    translate([0, 0, 4.5]) {
        cylinder(r=socket_diameter/2, h=socket_depth, $fn=20);
    }
}
```


[User]
I'd like to get a custom, parametric shelf bracket designed in OpenSCAD. I've got some requirements and a basic idea of how I want it to look. I need to be able to adjust the overall width of the bracket, its height, and its thickness, all in millimeters.

I'd like to have four different styles of support structures.

Style 1 would just have a single support that runs diagonally from the top beam to the vertical support, kind of like a triangle.

Style 2 should have multiple supports spaced evenly across the main beam.

Style 3 should have a single support like style one, but it should be positioned so it's closer to the front of the shelf, running from the corner of the top beam down to the vertical beam.

Style 4 should have two supports, mirrored across the vertical beam, in the same style as style 3, one in the front and another in the back.

I'm also going to need a couple of mounting holes on both sides of the vertical beam, offset a bit from the edges. The holes should go all the way through and have a countersink on each side.

Can you make sure the main beams have the width of the bracket I define, with some thickness, and the same height I specify? Also, the support elements should be the same thickness as the beams. And can you include a trim area to remove the extra space where the beams would overlap?

I don't need any specific libraries. Just a main .scad file to control the parameters and create the bracket. I'd also like the code to be commented so it's easy to understand what's going on. Thanks!

[Assistant]
shelf_bracket.scad:
```
// shelf_bracket.scad
// library for parametric wall shelf brackets
// Author: Tony Z. Tonchev, Michigan (USA)
// last update: November 2018

// (in mm)
Bracket_Width = 100;

// (in mm)
Bracket_Height = 20; //[15:50]

// (in mm)
Bracket_Thickness = 5; //[5:10]

Bracket_Style = 1; //[1:Support Style 1, 2:Support Style 2, 3:Support Style 3, 4:Support Style 4]

/* [Hidden] */

$fn=100;
TZT_W=Bracket_Width;
TZT_H=Bracket_Height;
TZT_S=Bracket_Style;
TZT_T=Bracket_Thickness;

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

TZT_Bracket ();

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

module TZT_Bracket () {
    difference () {
        intersection () {
            union () {
                TZT_BBeam ();
                rotate ([0,0,-90]) mirror ([0,1,0]) TZT_BBeam ();
                difference () {
                    translate ([0,-TZT_T*2,0]) cube ([TZT_T*2,TZT_T*2,TZT_H]);
                    translate ([TZT_T*2,-TZT_T*2,-1]) cylinder (TZT_H+2,TZT_T*1.5,TZT_T*1.5);
                }
                if (TZT_S==2) {
                    TZT_B2 ();
                } else if (TZT_S==3) {
                    TZT_B3 ();
                } else if (TZT_S==4) {
                    TZT_B4 ();
                } else {
                    TZT_B1 ();
                }
            }
            TZT_BTrim ();
        }
        TZT_BMount ();
    }

    module TZT_B1 () {
        TZT_BSupport ([TZT_W-TZT_T*3,TZT_W-TZT_T*3]);
    }
    module TZT_B2 () {
        for (TZT_i=[1:(TZT_W-TZT_T*3)/3:TZT_W-TZT_T*3+1])
            TZT_BSupport ([TZT_i,TZT_i]);
    }
    module TZT_B3 () {
        for (TZT_i=[(TZT_W-TZT_T*3)/3:(TZT_W-TZT_T*3)/3:TZT_W-TZT_T*3+1])
            TZT_BSupport ([TZT_i,TZT_W-TZT_T*3]);
    }
    module TZT_B4 () {
        for (TZT_i=[(TZT_W-TZT_T*3)/3:(TZT_W-TZT_T*3)/3:TZT_W-TZT_T*3-1]) {
            TZT_BSupport ([TZT_i,TZT_W-TZT_T*3]);
            rotate ([0,0,-90]) mirror ([0,1,0]) TZT_BSupport ([TZT_i,TZT_W-TZT_T*3]);
        }
    }
    module TZT_BBeam () {
        translate ([-TZT_T/2,-TZT_T/2,0]) {
            intersection () {
                translate ([TZT_W-TZT_T,TZT_T,0]) cylinder (TZT_H,TZT_T,TZT_T);
                cube ([TZT_W,TZT_T,TZT_H]);
            }
            cube ([TZT_W-TZT_T,TZT_T,TZT_H]);
        }
    }
    module TZT_BSupport (TZT) {
        hull () {
            translate ([TZT[0],0,0]) cylinder (TZT_H, TZT_T/2, TZT_T/2);
            translate ([0,-TZT[1],0]) cylinder (TZT_H, TZT_T/2, TZT_T/2);
        }
    }
    module TZT_BTrim () {
        translate ([-TZT_T/2,-TZT_W+TZT_T/2,0]) cube ([TZT_W, TZT_W, TZT_H]);
    }
    module TZT_BMount () {
        for (TZT_i=[0:1]) rotate (90*TZT_i,0,0) mirror ([TZT_i,0,0]) {
            translate ([TZT_T/3,-TZT_W*.1,TZT_H/2]) TZT_BMHole ();
            translate ([TZT_T/3,-TZT_W*.9,TZT_H/2]) TZT_BMHole ();
        }
        module TZT_BMHole () {
            rotate ([0,90,0]) {
                cylinder (TZT_W, 4, 4);
                translate ([0,0,-TZT_T*2]) cylinder (TZT_W, 1.5, 1.5);
            }
        }
    }
}
```


[User]
Hey, I'm looking to create a customizable box for storing small electronics and components. I've got some ideas about how it should be structured and how I'd like to be able to tweak it. It'll need to be parametric, so I can change its dimensions and features later.

First, the main box needs to have adjustable internal dimensions: width, length, and height. I'd like to specify these in millimeters. I'd like for there to be a base that can be either a solid floor or a grid pattern, that's where my electronics will sit. If it's a grid pattern, there should be an option between a square grid or a triangular grid. The grid will have a thickness that is smaller than the height of the base floor itself. I'd like the grid spacing and line width to also be adjustable.

The box will have walls, of course. I'd like for there to be an option to create triangle cutouts near the corners of the walls, kind of for decoration but also for reducing material use. Additionally, the walls should have "windows" (large cutouts) that can vary in depth, all the way from nearly closed to very large openings that take up a lot of the wall's surface.

Finally, it would be nice to have an option to generate just the base/floor of the box instead of the full thing, so I can use it as a lid for another box.

So, to summarize the features and parameters I'm looking for:

*   **Box Dimensions (mm, internal):**
    *   `box_width`
    *   `box_length`
    *   `box_height`
*   **Base Configuration:**
    *   `base_grid`:  `0` for solid, `1` for square grid, `2` for triangular grid.
    *    `grid_spacing`
    *    `grid_line_width`
    *    `grid_line_height`
    *    `base_height`
*   **Wall Features:**
    *   `wall_triangles`: `1` for triangle cutouts, `0` for no cutouts.
    *   `wall_windows`:  A float from `0` to `1` controlling the depth/size of the wall cutouts.
    *    `wall_thickness`

*   **Other:**
    *   `lid_only`: `0` for full box, `1` for base/floor only.
    *   `tower_size` : Size of the corner tower structures
    *   `interface_height` : Height of the interface bars and the corner buff-ups
    *    `corner_cutout_size`: Size of the corner cutouts at the very top of the walls.

The code should be able to use math functions, and I don't need any special libraries for this, it looks like it's all fairly standard stuff. Thanks!

[Assistant]
widgetbox.scad:
```
// mm (inside size)
box_width = 70; // [50:1:150]
// mm (inside size)
box_length = 110; // [50:1:150]
// mm (inside size)
box_height = 34; // [20:1:50]

// normal: 70, 110, 34

// extrabig:
//box_width = 120; // [50:5:150]
//box_length = 165; // [50:5:150]
//box_height = 40; // [20:1:50]

// liamspecial: 65,65,18

// Make a floor-only thing you can use as a lid?
lid_only = 0; // [0: No, 1:Yes]

// Use a grid as the base of the box?
base_grid = 2; // [2: Triangles, 1: Squares, 0:No]
// Trianglular cutouts near the corners of the walls?
wall_triangles = 1;// [1:Yes, 0:No]
// Depth of wall windows ? (0: No window, 1: A lot)
wall_windows = 1.0; // [0:0.01:1]

boxsz = [ box_width, box_length, box_height+1 ] * 1;

linew = 0.48 /1;
lineh = 0.2  /1;
towersz = linew*8;

interface_z = lineh * 20;

gridw = (linew*2) + 0.01;
gridsp = base_grid == 2 ? 8 : 5;
base_z = lineh * 4;

box_sl = box_width < box_length ? box_width : box_length;

triangle_sz = box_sl < 60 ? box_sl / 3 : 20;

wallw = linew*2;
ifch = interface_z - (lineh * 4);
uih = interface_z - (lineh * 8);
zf = 0.01/1;
zf2 = zf*2;

function polar_vect(dist, angle) = [ dist * cos(angle), dist * sin(angle) ];

/* This kinda blew my mind, so just look up there:
 * https://en.wikipedia.org/wiki/Line%E2%80%93line_intersection#Given_two_points_on_each_line
 */
function line_intersect(a, b) =
    [  ( /* x */
        (a[0].x*a[1].y - a[0].y*a[1].x) * (b[0].x - b[1].x)  -
        (a[0].x - a[1].x) * (b[0].x*b[1].y - b[0].y*b[1].x)
       ) / (
        (a[0].x - a[1].x) * (b[0].y - b[1].y) -
        (a[0].y - a[1].y) * (b[0].x - b[1].x)
       ),
       ( /* y */
        (a[0].x*a[1].y - a[0].y*a[1].x) * (b[0].y - b[1].y) -
        (a[0].y - a[1].y) * (b[0].x*b[1].y - b[0].y*b[1].x)
       ) / (
        (a[0].x - a[1].x) * (b[0].y - b[1].y) -
        (a[0].y - a[1].y) * (b[0].x - b[1].x)
       )
   ];

function angle(vector) = atan(vector.x / vector.y);

function InRange(v, l, h) = (v >= l) && (v <= h);

function LineInBox(fl, l) =
    let(
        is = [
            line_intersect(l, [[0,0],[0,1]]),
            line_intersect(l, [[0,0],[1,0]]),
            line_intersect(l, [[0,fl.y],[1,fl.y]]),
            line_intersect(l, [[fl.x,0],[fl.x,1]])
            ],
         si = InRange(is[0].y, 0, fl.y) ? 0 :
              (InRange(is[1].x, 0, fl.x) ? 1 :
              (InRange(is[2].x, 0, fl.x) ? 2 : 0)

              ),
         ei = InRange(is[3].y, 0, fl.y) ? 3 :
              (InRange(is[2].x, 0, fl.x) ? 2 :
              (InRange(is[1].x, 0, fl.x) ? 1 : 0)
              )
    )
    [ is[si], is[ei] ];

module TriFloorLine(fl, l) {
    a = angle(l[1] - l[0]);

    pv = polar_vect(gridw/2, a-90);
    nv = polar_vect(gridw/2, a+90);

    la = LineInBox(fl, [l[0] + pv,l[1] + pv]);
    lb = LineInBox(fl, [l[0] + nv,l[1] + nv]);

    pts = [ la[0], la[1], lb[1], lb[0] ];

    /* Omit crazy lines */
    v1 = InRange(la[0].x, 0, fl.x);
    v2 = InRange(la[1].x, 0, fl.x);
    v3 = InRange(lb[0].x, 0, fl.x);
    v4 = InRange(lb[1].x, 0, fl.x);

    v5 = InRange(la[0].y, 0, fl.y);
    v6 = InRange(la[1].y, 0, fl.y);
    v7 = InRange(lb[0].y, 0, fl.y);
    v8 = InRange(lb[1].y, 0, fl.y);

    if (v1 && v2 && v3 && v4 && v5 && v6 && v7 && v8)
        linear_extrude(base_z) polygon(pts);
}

module TriFloorLines(fl, y, g) {
    tri_l = [ g.x,  g.y / 2 ];
    tri_r = [ g.x, -g.y / 2 ];
    p1 = [ 0, y ];
    ll = [ p1, p1 + tri_l ];
    lr = [ p1, p1 + tri_r ];
    TriFloorLine(fl, ll);
    epl = line_intersect(ll, [[0,fl.y],[1,fl.y]]);
    if (epl.x < fl.x) {
       l2l = [ epl, epl + tri_r ];
       TriFloorLine(fl, l2l);
    }
    TriFloorLine(fl, lr);
    epr = line_intersect(lr, [[0,0],[1,0]]);
    if (epr.x < fl.x) {
        l2r = [ epr, epr - tri_l ];
        TriFloorLine(fl, l2r);
    }
}

module Walls(sz, w) {
    translate([-w, -w, 0]) {
        cube([sz.x + w*2, w, sz.z]);
        cube([w, sz.y + w*2, sz.z]);
    }
    translate([sz.x, -w, 0]) {
        cube([w, sz.y + w*2, sz.z]);
    }
    translate([-w, sz.y, 0]) {
        cube([sz.x + w*2, w, sz.z]);
    }
}

module CenterWalls(sz, w, bigw) {
    wextra = bigw - w;
    translate( [ -wextra/2, -wextra/2, 0 ] )
        Walls([sz.x + wextra, sz.y + wextra, sz.z], w);
}

module WindowCut(upw, lw, h, d) {
    wd = (upw - lw) / 2;
    pts = [ [ 0, 0 ],
            [ upw, 0 ],
            [ upw - wd, -h ],
            [ wd, -h ]
        ];
    linear_extrude(height = d, convexity= 10) polygon(pts);
}

module Corner(cut) {
    translate([-cut.x, -cut.x, 0]) {
        cube([cut.x, cut.y, cut.z]);
        cube([cut.y, cut.x, cut.z]);
    }
}

module WallCenterCorner(cut, wsz) {
    wextra = wsz - cut.x;
    translate( [ -wextra/2, -wextra/2, 0 ] )
        Corner(cut);
}
module WallCenterCorners(cut, wsz, box) {
    WallCenterCorner(cut, wsz);
    translate([0, box.y, 0]) rotate([0,0,-90])
        WallCenterCorner(cut, wsz);
    translate([box.x, box.y, 0]) rotate([0,0,180])
        WallCenterCorner(cut, wsz);
    translate([box.x, 0, 0]) rotate([0,0,90])
        WallCenterCorner(cut, wsz);

}

module CornerTri(sz) {
    pts = [
            [ 0, 0 ],
            [ sz.x, 0 ],
            [ 0, sz.y ]
        ];
    linear_extrude(height = sz.z, convexity=10) polygon(pts);
}
module BoxCornerTris(trisz, box) {
    CornerTri(trisz);
    translate([0, box.y, 0]) rotate([0,0,-90])
        CornerTri(trisz);
    translate([box.x, box.y, 0]) rotate([0,0,180])
        CornerTri(trisz);
    translate([box.x, 0, 0]) rotate([0,0,90])
        CornerTri(trisz);
}

function RoundDiv(total, divisor) = total / floor(total/divisor + 0.5);
function lerp(v0, v1, t) = (1 - t) * v0 + t * v1;

difference() {
    union() {
        towerz = lid_only ? interface_z : boxsz.z;
        /* Towers */
        for ( x = [ 0 - towersz, boxsz.x ] ) for ( y = [ 0 - towersz, boxsz.y ] ) {
            translate([x,y,0]) cube([towersz, towersz, towerz]);
        }
        /* Low interface bars */
        Walls([boxsz.x, boxsz.y, interface_z], towersz);
        /* Corner buff-ups */
        WallCenterCorners([linew*3, towersz*4, ifch+lineh], towersz*2, boxsz);
        if (base_grid) {
            /* Base grid */
            ydiv = RoundDiv(boxsz.y, gridsp);
            xdm = base_grid == 2 ? sqrt(3)/2 : 1;
            grid = [ RoundDiv(boxsz.x, ydiv * xdm), ydiv ];
            //echo(grid);
            for ( x = [ 0 : grid.x : boxsz.x+zf ] ) {
                olw = linew*1.2;

                translate([x - (gridw/2), -zf, lineh]) cube([gridw, boxsz.y+zf2, base_z+lineh]);
                translate([x - (olw/2), -zf, 0]) cube([olw, boxsz.y+zf2, lineh+zf]);

            }
            for ( y = [ 0: grid.y : boxsz.y+zf ] ) {
                if (base_grid == 2) {
                    translate([-zf, -zf, lineh]) TriFloorLines([boxsz.x+zf2,boxsz.y+zf2], y, grid);
                } else {
                    translate([-zf, y - (gridw/2), lineh]) cube([boxsz.x+zf2, gridw, base_z]);
                }

            }
            /* Triangles in the corners to improve attachment */
            BoxCornerTris([triangle_sz, triangle_sz, lineh*2], boxsz);
        } else {
            translate([-zf, -zf, 0]) cube([boxsz.x+zf, boxsz.y+zf2, base_z]);
        }
        if (!lid_only) {
            /* Walls (+ upper interface) */
            CenterWalls([boxsz.x, boxsz.y, boxsz.z + uih], wallw, towersz);
            /* Sharpen the very top of the corners to make them easier to insert */
            translate([0,0,boxsz.z+uih-zf]) WallCenterCorners([linew*1.2, towersz, 2*lineh+zf], towersz, boxsz);
        }
    }
    /* Circularize the tower corner cutouts */
    for ( x = [ 0 - towersz, boxsz.x ] ) for ( y = [ 0 - towersz, boxsz.y ] ) {
            translate([x,y,-zf])
        translate([towersz/2, towersz/2, 0 ])
            cylinder(r = towersz/2, h=ifch+zf, $fn=16);
    }

    /* Lower interface cutouts */
    ifcw = wallw + linew*2;
    translate([0,0,-zf]) {
        WallCenterCorners([ifcw, towersz*3, ifch+zf], towersz, boxsz);
        WallCenterCorners([ifcw+linew*2, towersz*3, lineh*2+zf], towersz, boxsz);
    }

    /* "Windows" aka the cutouts in the walls */
    wwh0 = uih + lineh*2;
    wwh1 = boxsz.z/2+uih;
    wlw0 = [ boxsz.x - towersz*4, boxsz.y - towersz*4 ];
    wlw1 = [ boxsz.x/2, boxsz.y/2 ];
    windowh = lerp(wwh0, wwh1, wall_windows);
    windowlw = [ lerp(wlw0.x, wlw1.x, wall_windows), lerp(wlw0.y, wlw1.y, wall_windows) ];

    translate([towersz, 0, boxsz.z+uih+zf]) rotate([90,0,0])
        WindowCut(boxsz.x - towersz*2, windowlw.x, windowh, towersz);
    translate([towersz, boxsz.y+towersz, boxsz.z+uih+zf]) rotate([90,0,0])
        WindowCut(boxsz.x - towersz*2, windowlw.x, windowh, towersz);
    translate([0, boxsz.y - towersz, boxsz.z+uih+zf]) rotate([90,0,-90])
        WindowCut(boxsz.y - towersz*2, windowlw.y, windowh, towersz);
    translate([boxsz.x+towersz, boxsz.y - towersz, boxsz.z+uih+zf]) rotate([90,0,-90])
        WindowCut(boxsz.y - towersz*2, windowlw.y, windowh, towersz);

    /* The near-corner triangle cutouts in the walls */
    if (wall_triangles) {
        trcuth = 8;
        /* Short sides */
        translate([zf,0,trcuth]) rotate([90,0,0]) CornerTri([boxsz.x/6, boxsz.z/2, towersz]);
        translate([boxsz.x-zf,-towersz,trcuth]) rotate([90, 0, 180]) CornerTri([boxsz.x/6, boxsz.z/2, towersz]);
        translate([zf,boxsz.y+towersz,trcuth]) rotate([90,0,0]) CornerTri([boxsz.x/6, boxsz.z/2, towersz]);
        translate([boxsz.x-zf,boxsz.y,trcuth]) rotate([90, 0, 180]) CornerTri([boxsz.x/6, boxsz.z/2, towersz]);
        /* Long sides */
        translate([-towersz,zf,trcuth]) rotate([90,0,90]) CornerTri([boxsz.y/6, boxsz.z/2, towersz]);
        translate([0,boxsz.y-zf,trcuth]) rotate([90,0,-90]) CornerTri([boxsz.y/6, boxsz.z/2, towersz]);
        translate([boxsz.x,zf,trcuth]) rotate([90,0,90]) CornerTri([boxsz.y/6, boxsz.z/2, towersz]);
        translate([boxsz.x+towersz,boxsz.y-zf,trcuth]) rotate([90,0,-90]) CornerTri([boxsz.y/6, boxsz.z/2, towersz]);
    }

}
```


[User]
I'm looking to create a parametric wall shelf bracket, and I'd like the design to be flexible enough to suit different shelf sizes and styles. I've seen some good examples but I want to build mine from scratch. Here are the key features I'd like included:

1.  **Dimensions:** I need to be able to adjust the bracket's width, height, and thickness. These should be configurable parameters so I can adjust them easily. I'm thinking in millimeters, and it'd be nice if there were reasonable default values in place.

2.  **Multiple Support Styles:** I'm envisioning a few different support structures connecting the two bracket arms. I'd like to be able to easily switch between these styles via a single parameter, ideally with an integer indicating the chosen style. I have a few different concepts for those supports that are worth exploring:
    *   **Style 1:**  Include a few small support cylinders at varying angles/positions between the top and back arms
    *   **Style 2:** Have multiple support cylinders connecting the arms where the cylinders are equally spaced between the two arms and move in parallel
    *   **Style 3:** Have multiple support cylinders that do not move in parallel - they are spaced equally but their distance from the edge of the arms varies from one to the next
    *   **Style 4:** Include one support cylinder running from one corner to the other of the inner part of the bracket and one in reverse.

3.  **Mounting Holes:** The bracket needs mounting holes for attaching it to the wall. I'd prefer two holes on each side of the bracket and the holes should have counterbores/countersinks.

4.  **Construction:**
    *   The main beams of the bracket should have a rectangular profile with a rounded edge on the outside, similar to a half cylinder that is combined with a rectangle.
    *   The supports should be cylinders.
    *   There should be a section of the corner that is removed by intersecting a rectangular prism with the beams to create a clean edge.

I'm hoping that all of these are parametric so I can easily tweak the bracket to different mounting applications. I'm not particularly concerned about tolerances at this point, but I would like a smooth appearance. I'm also imagining that all of the above will be within a single file with custom modules.

I don't need any external libraries for this. Could you help me with this?

[Assistant]
shelf_bracket_A.scad:
```
// shelf_bracket_A.scad
// library for parametric wall shelf brackets
// Author: Tony Z. Tonchev, Michigan (USA)
// last update: November 2018

// (in mm)
Bracket_Width = 100;

// (in mm)
Bracket_Height = 20; //[15:50]

// (in mm)
Bracket_Thickness = 5; //[5:10]

Bracket_Style = 1; //[1:Support Style 1, 2:Support Style 2, 3:Support Style 3, 4:Support Style 4]

/* [Hidden] */

$fn=100;
TZT_W=Bracket_Width;
TZT_H=Bracket_Height;
TZT_S=Bracket_Style;
TZT_T=Bracket_Thickness;

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

TZT_Bracket ();

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

module TZT_Bracket () {
    difference () {
        intersection () {
            union () {
                TZT_BBeam ();
                rotate ([0,0,-90]) mirror ([0,1,0]) TZT_BBeam ();
                difference () {
                    translate ([0,-TZT_T*2,0]) cube ([TZT_T*2,TZT_T*2,TZT_H]);
                    translate ([TZT_T*2,-TZT_T*2,-1]) cylinder (TZT_H+2,TZT_T*1.5,TZT_T*1.5);
                }
                if (TZT_S==2) {
                    TZT_B2 ();
                } else if (TZT_S==3) {
                    TZT_B3 ();
                } else if (TZT_S==4) {
                    TZT_B4 ();
                } else {
                    TZT_B1 ();
                }
            }
            TZT_BTrim ();
        }
        TZT_BMount ();
    }

    module TZT_B1 () {
        translate ([TZT_W/3,-TZT_W/3,0]) TZT_BSupport (TZT_W/3);
        translate ([TZT_W*0.72,-TZT_W/8,0]) TZT_BSupport (TZT_W/8);
        translate ([TZT_W/8,-TZT_W*0.72,0]) TZT_BSupport (TZT_W/8);
    }
    module TZT_B2 () {
        TZT_v=TZT_W/5;
        for (TZT_i=[TZT_v*2:TZT_v:TZT_W])
            translate ([TZT_i-TZT_v*2+TZT_T,-TZT_W+TZT_i-TZT_T,0])
            TZT_BSupport (TZT_v);
    }
    module TZT_B3 () {
        TZT_v=TZT_W/10;
        for (TZT_i=[TZT_v*2.1:TZT_v*2.1:TZT_v*9])
            TZT_BSupport (TZT_i);
    }
    module TZT_B4 () {
        translate ([-TZT_W*0.5,0,0]) TZT_BSupport (TZT_W);
        translate ([0,TZT_W*0.5,0]) TZT_BSupport (TZT_W);
    }

    module TZT_BBeam () {
        translate ([-TZT_T/2,-TZT_T/2,0]) {
            intersection () {
                translate ([TZT_W-TZT_T,TZT_T,0]) cylinder (TZT_H,TZT_T,TZT_T);
                cube ([TZT_W,TZT_T,TZT_H]);
            }
            cube ([TZT_W-TZT_T,TZT_T,TZT_H]);
        }
    }
    module TZT_BSupport (TZT) {
        difference () {
            cylinder (TZT_H, TZT, TZT);
            translate ([0,0,-1]) cylinder (TZT_H+2, TZT-TZT_T, TZT-TZT_T);
        }
    }
    module TZT_BTrim () {
        translate ([-TZT_T/2,-TZT_W+TZT_T/2,0]) cube ([TZT_W, TZT_W, TZT_H]);
    }
    module TZT_BMount () {
        for (TZT_i=[0:1]) rotate (90*TZT_i,0,0) mirror ([TZT_i,0,0]) {
            translate ([TZT_T/3,-TZT_W*.1,TZT_H/2]) TZT_BMHole ();
            translate ([TZT_T/3,-TZT_W*.9,TZT_H/2]) TZT_BMHole ();
        }
        module TZT_BMHole () {
            rotate ([0,90,0]) {
                cylinder (TZT_W, 4, 4);
                translate ([0,0,-TZT_T*2]) cylinder (TZT_W, 1.5, 1.5);
            }
        }
    }
}
```


[User]
Okay, I'm looking to create a customizable card tray, similar to the one I saw online, but I need it to be fully parametric. I'd like to be able to specify a few things:

*   **Card Dimensions:** The width and height of the cards that will go into the tray.
*   **Box Height:** The overall height of the box.
*   **Number and Width of Slots:** I'd like to specify the number of card slots as well as the width of each slot.
*   **Number of Rows:** I also want to be able to define how many rows of card slots I want.
*   **Slanted Front:** It would be great if I could choose whether the front of the tray is slanted or vertical to match the dividers.
*   **Labels:** I'd also like to add labels to each of the card slots. (ideally these labels would appear on either side of the tray)
*  **Bottom Cutout**: There should be a cutout at the bottom to reduce plastic, the size of which I can configure.
*   **Top Access Slot:** There should be a top access slot and it should be possible to adjust the depth.
*   **Wall Thickness:** I'll need to be able to adjust the thickness of the walls.
*   **Rounding:** The corners of the box should be rounded.

The key design feature of the card slots is that the cards will be tilted backwards so they fit within the box height. The tilt angle should be automatically calculated so the top of the cards hits the top of the box, accounting for wall thickness. The length of the box should be calculated to account for the sum of the slot widths, the extra length from the card tilt, and the divider thicknesses. Also, each divider should have a thickness that should be configurable. The labels should be oriented such that they read left to right when looking at the sides of the tray.

I don't have much Openscad experience so if you could provide the code that uses the standard openscad modules (like cube, sphere, translate, rotate, etc) instead of something like BOSL, that would be easiest for me to understand.

[Assistant]
CardTray.scad:
```
// Width of a single card
CardWidth = 96;

// Height of a single card
CardHeight = 68;

// Box Height
BoxHeight = 70;

// Size of each Card slot
Slots = [12,30,100];

// Number of rows of cards
Rows = 1;

// Slant the front of the box
SlantFront = true;

// Labels for each card slot  (only recommended when Rows=1)
Labels = ["Jacks", "Foundations", "Buildings"];

// Size of botton cutout, % of width
Removal = 0.4;
AccessDepth = 0.4;

// Wall Thickness
gWT = 1.6;

// Roundness
$fn = 20;

function SumList(list, start, end) = (start == end) ? list[start] : list[start] + SumList(list, start+1, end);

module RCube(x,y,z,ipR=4) {
    translate([-x/2,-y/2,0]) hull(){
      translate([ipR,ipR,ipR]) sphere(ipR);
      translate([x-ipR,ipR,ipR]) sphere(ipR);
      translate([ipR,y-ipR,ipR]) sphere(ipR);
      translate([x-ipR,y-ipR,ipR]) sphere(ipR);
      translate([ipR,ipR,z-ipR]) sphere(ipR);
      translate([x-ipR,ipR,z-ipR]) sphere(ipR);
      translate([ipR,y-ipR,z-ipR]) sphere(ipR);
      translate([x-ipR,y-ipR,z-ipR]) sphere(ipR);
      }
}

Angle = (((BoxHeight-gWT)/CardHeight) < 1) ? acos((BoxHeight-gWT)/CardHeight) : 0;

//Wall space for tilted wall
gWS =  gWT / cos(Angle);
BoxWidth = CardWidth + 2*gWT;

SlotsAdj = [for (i = [0:len(Slots)-1]) Slots[i]/cos(Angle)];
ExtraLength = CardHeight * sin(Angle);
BoxLength = SumList(SlotsAdj,0,len(SlotsAdj)-1) + ExtraLength + (len(Slots)-1) * gWS+ 2*gWT;
RailPlace = [for (i = [0:len(Slots)-1]) gWT-BoxLength/2+SumList(SlotsAdj,0,i)+gWS*i ];
LabelPlace = [for (i = [0:len(Slots)-1])  (i == 0) ? ((-BoxLength/2)+RailPlace[0])/2 + ExtraLength : (RailPlace[i-1] + RailPlace[i])/2 + ExtraLength];

// final dimensions
echo(BoxLength,BoxWidth, Angle);

//  Main Box
module Box() {
   intersection()
   {
     RCube(BoxLength,BoxWidth,BoxHeight, 1);
     difference()
     {
        union()
        {
           difference()
           {
              RCube(BoxLength,BoxWidth,BoxHeight, 1);

              // Hallow out the box
              translate([gWT/2,0,BoxHeight/2+gWT]) cube([BoxLength-gWT,BoxWidth-2*gWT,BoxHeight], center=true);

              // Add the names to both sides
              for(x=[0:len(Slots)-1]) {
                    translate ([LabelPlace[x],-BoxWidth/2+0.4,BoxHeight-gWT])rotate([90,0,0]) linear_extrude(0.4) text(Labels[x], size = 4, spacing = 0.9, direction = "ttb",  font="Helvetica:style=Bold");
                    translate ([LabelPlace[x],BoxWidth/2-0.4,BoxHeight-gWT])rotate([90,0,180]) linear_extrude(5) text(Labels[x], size = 4, spacing = 0.9, direction = "ttb",  font="Helvetica:style=Bold");
                 }  // end For
           }  // shell of box

           // add the dividers
           for(x=[0:len(Slots)-1]) {
              translate([RailPlace[x]-0.2,0,gWT-CardHeight/2])  translate([1,0,CardHeight/2]) rotate([0,Angle,0]) translate([0,0,CardHeight/2]) cube([2, CardWidth, CardHeight],center=true);
           }

           // Add new front if configured
           if (SlantFront)
           {
               translate([-BoxLength/2,0,gWT]) rotate([0,Angle,0]) translate([0,0,CardHeight/2]) cube([2, CardWidth, CardHeight],center=true);
           }
        } // End the union after here is substraction

        // create gap at top to access the cards
        AccessWidth = CardWidth * 0.4;
        hull(){
            translate([0,-AccessWidth/2+6,BoxHeight+10]) rotate([0,90,0])cylinder(r=6,h=BoxLength,center=true);;
            translate([0,AccessWidth/2-6,BoxHeight+10]) rotate([0,90,0])cylinder(r=6,h=BoxLength,center=true);;
            translate([0,-AccessWidth/2+6,BoxHeight*(1-AccessDepth)])rotate([0,90,0])cylinder(r=6,h=BoxLength,center=true);;
            translate([0,AccessWidth/2-6,BoxHeight*(1-AccessDepth)])rotate([0,90,0])cylinder(r=6,h=BoxLength,center=true);;
        } // hull

            translate([0,-AccessWidth/2-6,BoxHeight-6])difference(){
               cube([BoxLength,12.1,12.1], center = true);
               rotate([0,90,0])cylinder(r=6,h=BoxLength,center=true);
                translate([0,-6,0])cube([BoxLength,12,12], center = true);
                translate([0,0,-6])cube([BoxLength,12,12], center = true);
            }
           translate([0,+AccessWidth/2+6,BoxHeight-6]) difference(){
               cube([BoxLength,12.1,12.1], center = true);
               rotate([0,90,0])cylinder(r=6,h=BoxLength,center=true);
                translate([0,6,0])cube([BoxLength,12,12], center = true);
                translate([0,0,-6])cube([BoxLength,12,12], center = true);
            }
//           rotate([0,90,0]) triangle(6, 6, BoxLength+10, center = true);

        // Remove some from the bottem to reduce plastic
        hull() {
            translate([BoxLength/2-(BoxWidth*Removal/2)-15,0,0]) sphere(r=(BoxWidth*Removal)/2);
            translate([-BoxLength/2+(BoxWidth*Removal/2)+15,0,0]) sphere (r=(BoxWidth*Removal)/2);
        }

        // If we have the slanted front remove part of the box
        if (SlantFront)
        {
           hull() {
             translate([-BoxLength/2-200,0,gWT]) rotate([0,Angle,0]) translate([0,0,CardHeight/2]) cube([2, CardWidth+10, CardHeight+2*gWT],center=true);
             translate([-BoxLength/2-2,0,gWT]) rotate([0,Angle,0]) translate([0,0,CardHeight/2]) cube([2, CardWidth+10, CardHeight+2*gWT],center=true);
              }
        } // end slant
      } // end diff
   }  // Instersection
}

for(i=[0:Rows-1]) { translate([0,i * (BoxWidth-gWT),0]) Box(); }

```


[User]
I'm looking to create a parametric Lego backpack adapter in OpenSCAD. I want to be able to attach it to my own 3D printed models. I need to specify the dimensions of the Lego part of the adapter in terms of studs – specifically the width, length, and height. I also need to choose if the connection to my model uses one or two pins and specify the pin height, as well as whether the lego connection is standard studs or antistuds.

Specifically, I want the following customizable parameters:

*   `lego_width`:  The width of the Lego brick part, measured in studs.
*   `lego_length`: The length of the Lego brick part, measured in studs.
*   `lego_height`: The height/thickness of the Lego brick part, measured in plate heights (e.g., a standard brick is 3 plate heights).
*   `isTwoPins`:  A choice of "One" or "Two" indicating how many pins to use for connecting to the model.
*    `pinHeight`:  The height of the pins extending into my model.
*    `mode`: A choice of "studs" or "antistuds" to change the lego connector.

The design should include:
*   The appropriate lego dimensions based on the `lego_length`, `lego_width`, and `lego_height`. I think that means that there is a fixed unit of `FLU = 1.6 mm` and a `BRICK_WIDTH = 5*FLU`.
*   The pins need to be correctly placed and sized to connect to a typical lego brick.
*   The lego connection needs to include the appropriate studs or antistuds.
*   It needs to use the `lego_brick_builder.scad` library to create the Lego connector.

Could you generate the necessary OpenSCAD files, including the main file and any modules or files required to integrate the `lego_brick_builder.scad` library?

[Assistant]
lego_backpack.scad:
```
 use <lego_brick_builder.scad>;

/* [Hidden] */

FLU = 1.6; // Fundamental Lego Unit = 1.6 mm
BRICK_WIDTH = 5*FLU; // basic brick width

/* [Block Dimensions] */
// when attached to your model, how wide is the adapter in studs.
lego_width =      2;
// when attached to your model, how tall is the adapter in studs.
lego_length =     2;
// when attached to your model, how thick is the adapter in studs.
lego_height = 1;

/* [Adapter Settings] */
// does this connect via one pin or two.
isTwoPins = "Two"; //  [One, Two]
// how tall are the pins that extend into the body?
pinHeight =      3.9;

PinOffset = (isTwoPins == "Two") ? 1 : 0;

translate([0,-BRICK_WIDTH*lego_width/2,0])  brick(lego_length,lego_width,lego_height);
brickSolid(lego_length,lego_width, lego_height);
pins();

module brickSolid(lego_length,lego_width, lego_height){
    translate([0,BRICK_WIDTH*lego_width/-2,0])  cube(size=[
    lego_length*BRICK_WIDTH,
    lego_width*BRICK_WIDTH,
    lego_height*FLU*2-.1]);
}

module pins(zOffset=1, dOffset=0){
    offsetValue = 4.65;
    translate([BRICK_WIDTH*lego_length/2,0,-pinHeight*zOffset/2])  for (ix = [-1,1]){
        translate([0,offsetValue*ix*PinOffset,0]) cylinder(d=2.9+dOffset, h=pinHeight, center=true, $fn=50);
    }
}
```
lego_brick_builder.scad:
```
/*

 Basic Lego brick builder module for OpenScad by Jorg Janssen 2013 (CC BY-NC 3.0)
 To use this in your own projects add:

 use <path_to_this_file/lego_brick_builder.scad>
 brick (length, width, height [,smooth]);

 Length and width are in standard lego brick dimensions.
 Height is in flat brick heights, so for a normal lego brick height = 3.
 Add optional smooth = true for a brick without studs.
 Use height = 0 to just put studs/knobs on top of other things.

 */
$fn = 150;

 // this is it:
brick(5,3,3);

// and this is how it's done:

FLU = 1.6; // Fundamental Lego Unit = 1.6 mm

BRICK_WIDTH = 5*FLU; // basic brick width
BRICK_HEIGHT = 6*FLU; // basic brick height
PLATE_HEIGHT = 2*FLU; // basic plate height
WALL_THICKNESS = FLU; // outer wall of the brick
STUD_RADIUS = 1.5*FLU; // studs are the small cylinders on top of the brick with the lego logo ('nopje' in Dutch)
STUD_HEIGHT = FLU;
ANTI_STUD_RADIUS = 0.5*4.07*FLU;  // an anti stud is the hollow cylinder inside bricks that have length > 1 and width > 1
PIN_RADIUS = FLU; // a pin is the small cylinder inside bricks that have length = 1 or width = 1
SUPPORT_THICKNESS = 0.254; // support is the thin surface between anti studs, pins and walls, your printer might not print this thin, try thicker!
EDGE = 0.254; // this is the width and height of the bottom line edge of smooth bricks
CORRECTION = 0.1; // addition to each size, to make sure all parts connect by moving them a little inside each other

module brick(length = 4, width = 2, height = 3, smooth = false){

	// brick shell
	difference(){
		cube(size = [length*BRICK_WIDTH,width*BRICK_WIDTH,height*PLATE_HEIGHT]);
		translate([WALL_THICKNESS,WALL_THICKNESS,-WALL_THICKNESS])
		union(){
			cube(size = [length*BRICK_WIDTH-2*WALL_THICKNESS,width*BRICK_WIDTH-2*WALL_THICKNESS,height*PLATE_HEIGHT]);
			// stud inner holes, radius = pin radius
			if (!smooth) {
				translate([STUD_RADIUS+WALL_THICKNESS,STUD_RADIUS+WALL_THICKNESS,height*PLATE_HEIGHT])
				for (y = [0:width-1]){
					for (x = [0:length-1]){
						translate ([x*BRICK_WIDTH-WALL_THICKNESS,y*BRICK_WIDTH-WALL_THICKNESS,-CORRECTION])
						cylinder(h=WALL_THICKNESS+2*CORRECTION,r=PIN_RADIUS);
					}
				}
			}
			// small bottom line edge for smooth bricks
			else {
				translate([-WALL_THICKNESS-CORRECTION,-WALL_THICKNESS-CORRECTION,FLU-CORRECTION])
				difference() {
					cube([length*BRICK_WIDTH+2*CORRECTION,width*BRICK_WIDTH+2*CORRECTION,EDGE+CORRECTION]);
					translate([EDGE+CORRECTION,EDGE+CORRECTION,-CORRECTION])
					cube([length*BRICK_WIDTH-2*EDGE,width*BRICK_WIDTH-2*EDGE,EDGE+3*CORRECTION]);
				}
			}
		}
	}
	// Studs
	if(!smooth){
		translate([STUD_RADIUS+WALL_THICKNESS,STUD_RADIUS+WALL_THICKNESS,height*PLATE_HEIGHT])
		for (y = [0:width-1]){
			for (x = [0:length-1]){
				translate ([x*BRICK_WIDTH,y*BRICK_WIDTH,-CORRECTION])
				difference(){
					cylinder(h=STUD_HEIGHT+CORRECTION, r=STUD_RADIUS);
					// Stud inner holes
					translate([0,0,-CORRECTION])
					cylinder(h=0.5*STUD_HEIGHT+CORRECTION,r=PIN_RADIUS);
				}
				// tech logo - disable this if your printer isn't capable of printing this small
				if ( length > width){
					translate([x*BRICK_WIDTH+0.8,y*BRICK_WIDTH-1.9,STUD_HEIGHT-CORRECTION])
					resize([1.2*1.7,2.2*1.7,0.254+CORRECTION])
					rotate(a=[0,0,90])
					import("tech.stl");
				}
				else {
					translate([x*BRICK_WIDTH-1.9,y*BRICK_WIDTH-0.8,STUD_HEIGHT-CORRECTION])
					resize([2.2*1.7,1.2*1.7,0.254+CORRECTION])
					import("tech.stl");
				}
				/*
				// Alternative 2-square logo
				translate ([x*BRICK_WIDTH+CORRECTION,y*BRICK_WIDTH-CORRECTION,STUD_HEIGHT-CORRECTION])
				cube([1,1,2*CORRECTION]);
				translate ([x*BRICK_WIDTH-0.9,y*BRICK_WIDTH-0.9,STUD_HEIGHT-CORRECTION])
				cube([1,1,0.3]);
				*/
			}
		}
	}
	// Pins x
	if (width == 1 && length > 1) {
			for (x = [1:length-1]){
				translate([x*BRICK_WIDTH,0.5*BRICK_WIDTH,0])
				cylinder(h=height*PLATE_HEIGHT-WALL_THICKNESS+CORRECTION,r=PIN_RADIUS);
				// Supports
				if (height > 1) {
				translate([x*BRICK_WIDTH-0.5*SUPPORT_THICKNESS,CORRECTION,STUD_HEIGHT])
				cube(size=[SUPPORT_THICKNESS,BRICK_WIDTH-2*CORRECTION,height*PLATE_HEIGHT-STUD_HEIGHT-WALL_THICKNESS+CORRECTION]);
			}
		}
	}
	// Pins y
	if (length == 1 && width > 1) {
			for (y = [1:width-1]){
			translate([0.5*BRICK_WIDTH,y*BRICK_WIDTH,0])
			cylinder(h=height*PLATE_HEIGHT-WALL_THICKNESS+CORRECTION,r=PIN_RADIUS);
			// Supports
			if (height > 1) {
			translate([CORRECTION,y*BRICK_WIDTH-0.5*SUPPORT_THICKNESS,STUD_HEIGHT])
			cube(size=[BRICK_WIDTH-2*CORRECTION,SUPPORT_THICKNESS,height*PLATE_HEIGHT-STUD_HEIGHT-WALL_THICKNESS+CORRECTION]);}

		}
	}
	// Anti Studs
	if (width > 1 && length > 1){
		difference(){
			union(){
				for(y = [1:width-1]){
					for(x = [1:length-1]){
						// anti studs
						translate([x*BRICK_WIDTH,y*BRICK_WIDTH,0])
						cylinder (h=height*PLATE_HEIGHT-WALL_THICKNESS+CORRECTION, r = ANTI_STUD_RADIUS);
						// Supports
						if (height > 1){
							// Support x
							if (x%2 == 0 && (length%2 == 0 || length%4 == 1 && x<length/2 || length%4 == 3 && x>length/2) || x%2 == 1 && (length%4 == 3 && x<length/2 || length%4 == 1 && x>length/2)) {
								translate([BRICK_WIDTH*x-0.5*SUPPORT_THICKNESS,y*BRICK_WIDTH-BRICK_WIDTH+WALL_THICKNESS-CORRECTION,STUD_HEIGHT])
								cube(size=[SUPPORT_THICKNESS,2*BRICK_WIDTH-2*WALL_THICKNESS,height*PLATE_HEIGHT-STUD_HEIGHT-WALL_THICKNESS+CORRECTION]);
							}
							// Supports y
							if (y%2 == 0 && (width%2 == 0 || width%4 == 1 && y<width/2 || width%4 == 3 && y>width/2) || y%2 == 1 && (width%4 == 3 && y<width/2 || width%4 == 1 && y>width/2)) {
								translate([x*BRICK_WIDTH-BRICK_WIDTH+WALL_THICKNESS-CORRECTION,BRICK_WIDTH*y-0.5*SUPPORT_THICKNESS,STUD_HEIGHT])
								cube(size=[2*BRICK_WIDTH-2*WALL_THICKNESS,SUPPORT_THICKNESS,height*PLATE_HEIGHT-STUD_HEIGHT-WALL_THICKNESS+CORRECTION]);
							}
						}
					}
				}
			}
			union(){
				for(y = [1:width-1]){
					for(x = [1:length-1]){
						// hollow anti studs
						translate([x*BRICK_WIDTH,y*BRICK_WIDTH,-WALL_THICKNESS])
						cylinder (h=height*PLATE_HEIGHT, r = STUD_RADIUS);
					}
				}
			}
		}
	}
}

```
lego_backpack_v2.scad:
```
 use <lego_brick_builder.scad>;

/* This file requires:
Basic Lego brick builder module for OpenScad by Jorg Janssen 2013 (CC BY-NC 3.0)

If the file is not included, it may be downloaded from:

https://web.archive.org/web/20150923213552/https://thingiverse-production-new.s3.amazonaws.com/assets/f8/b1/71/ea/fb/lego_brick_builder.scad

*/

/* [Hidden] */

FLU = 1.6; // Fundamental Lego Unit = 1.6 mm
BRICK_WIDTH = 5*FLU; // basic brick width

/* [Block Dimensions] */
// when attached to your model, how wide is the adapter in studs.
lego_width =      2;
// when attached to your model, how tall is the adapter in studs.
lego_length =     2;
// when attached to your model, how thick is the adapter in studs.
lego_height = 1;

/* [Adapter Settings] */
// does this connect via one pin or two.
isTwoPins = "Two"; //  [One, Two]
// how tall are the pins that extend into the body?
pinHeight =      3.9;
// which mode do you want to make? studs or anti-studs
mode = "studs"; // [studs, antistuds]

PinOffset = (isTwoPins == "One") ? 0 : 1;

module backpack(lego_width = lego_width, lego_length = lego_length){
    translate([0,0,lego_height*FLU*2 * (mode == "antistuds" ? 1 : 0)])
    mirror([0,0,mode == "antistuds" ? 1 : 0])
    translate([0,-BRICK_WIDTH*lego_width/2,0])  brick(lego_length,lego_width,lego_height, mode == "antistuds");

    if (mode != "antistuds"){
        brickSolid(lego_length,lego_width, lego_height);
    }
    pins(lego_length = lego_length);
}

backpack(lego_width,lego_length);

module brickSolid(lego_length,lego_width, lego_height){
    translate([0,BRICK_WIDTH*lego_width/-2,0])  cube(size=[
    lego_length*BRICK_WIDTH,
    lego_width*BRICK_WIDTH,
    lego_height*FLU*2-.1]);
}

module pins(zOffset=1, dOffset=0,     lego_length = lego_length){
    offsetValue = 4.65;
    translate([BRICK_WIDTH*lego_length/2,0,-pinHeight*zOffset/2])  for (ix = [-1,1]){
        translate([0,offsetValue*ix*PinOffset,0]) cylinder(d=2.9+dOffset, h=pinHeight, center=true, $fn=50);
    }
}
```


[User]
I'm looking to create a Raspberry Pi mount for my Prusa i3 MK2S printer. It should clamp onto the vertical aluminum frame of the printer. I have a design I’ve been working with in OpenSCAD, but I’d like a more flexible, parametric version so it can be easily adapted for different frame sizes.

The basic design consists of a main body that wraps around the vertical frame. There are two vertical parts that sit on either side of the frame, and horizontal parts that connect them. The Pi is held in place by two pairs of clips, one pair on top and one pair at the bottom.  Additionally, I have some mount points for screws and "anti-cracking" holes.

Here’s a breakdown of the key features and parameters I need:

**Parameters:**

*   `frame_w`: The width of the printer's aluminum frame. This should be adjustable.
*   `frame_t`: The thickness of the printer's aluminum frame. This should be adjustable.
*   `mount_pad`: Boolean value. Enables/disables mounting pads, and related mounting holes, if set to 1, otherwise disabled.
*   `pi_width`: The width of the raspberry pi to be mounted.
*   `pi_length`: The length of the raspberry pi to be mounted.
*   `pi_height`: The height of the raspberry pi to be mounted.
*  `clip_gap`: the gap between the two clip parts of a pair.

**Features:**

*   **Frame Mount:** The main structure should wrap around the vertical frame of the Prusa i3. This means I need two vertical pieces and two horizontal pieces joining them. The dimensions of these pieces should be based on `frame_w` and `frame_t`.
*   **Pi Clips:** There should be four clips to hold the Raspberry Pi. Two on the top, two on the bottom. They should be positioned based on the Pi dimensions, and ideally there would be a small gap `clip_gap` to make it easier to insert the Pi.
*   **Mounting Pads:**  Optional cylindrical pads for mounting. These should be controlled with the mount_pads variable, and should also include mounting holes, and countersink holes.
*   **Anti-Crack Holes:** Small cylindrical holes should be added at internal corners to prevent cracking, as shown in my original design.
*   **Material Thickness:** All parts should have the proper thickness for 3D printing.
*   **Clearances**: should have a small clearance added to any interlock parts for easier assembly.

I'd like the design to be fully parametric, so I can easily adjust the dimensions if I change the frame or want to use it for a different Raspberry Pi model.

I'm hoping you can provide a parametric OpenSCAD file or files that I can use. I'm not using any special libraries like MCAD or BOSL, so a simple, clean implementation without external libraries would be ideal.

[Assistant]
prusa_MK2S_mount_V3.scad:
```
//Mark Benson
// CC NC 2013
//
//Raspberry Pi mount for Aluminium frame (6mm) Prusa i3
//
//Remixed Niels4140 2019

// Variables
pads = 1; //[0,1]
frame_w = 55.3; //[45:100]
frame_t = 6; // [1:10]

mount(pads); //
module mount(pads = 1){
delta = 0.1; //
translate([0,0,0])
rotate(a=0, v=[0,0,0])
difference()
{
	union()
	{
//Mounting pads
if (pads==1){

	color("green") translate([80,18,0]) rotate(a=0, v=[0,0,0]) cylinder(r=4, h=6, $fn=25);
	color("green") translate([25.5,43.5,0]) rotate(a=0, v=[0,0,0]) cylinder(r=4, h=6, $fn=25);
}

	//Frame
	%translate([0, 4, 6]) cube([200, frame_w, frame_t]);

	//Vertical parts
	translate([25.5-3,0,0]) rotate([0,0,0]) cube([6,frame_w+6,6]);
	translate([80-3,0,0]) rotate([0,0,0]) cube([6,frame_w+6,6]);

	//Horizontal parts
	translate([25.5,18-2,0]) rotate([0,0,0]) cube([54.5,4,6]);
	translate([25.5,56-12.5-2,0]) rotate([0,0,0]) cube([54.5,4,6]);

	//Pi Clips

	//Uprights
	translate([25.5-3,-2,0]) rotate([0,0,0]) cube([6,6,frame_t+10]);
	translate([80-3,-2,0]) rotate([0,0,0]) cube([6,6,frame_t+10]);
	translate([25.5-3,frame_w+4,0]) rotate([0,0,0]) cube([6,6,frame_t+10]);
	translate([80-3,frame_w+4,0]) rotate([0,0,0]) cube([6,6,frame_t+10]);

	//Clips
	translate([25.5-3,2.5,frame_t+8.3]) rotate(a=90, v=[0,1,0]) cylinder(r=2.5, h=6, $fn=25);
	translate([80-3,2.5,frame_t+8.3]) rotate(a=90, v=[0,1,0]) cylinder(r=2.5, h=6, $fn=25);
	color("red") translate([25.5-3,frame_w+5,frame_t+8.3]) rotate(a=90, v=[0,1,0]) cylinder(r=2.5, h=6, $fn=25);
	color("red") translate([80-3,frame_w+5,frame_t+8.3]) rotate(a=90, v=[0,1,0]) cylinder(r=2.5, h=6, $fn=25);
/*
	//Spacer pads
	color("green") translate([40,30,0]) rotate(a=0, v=[0,0,0]) cylinder(r=3, h=3, $fn=25);
	color("green") translate([60,30,0]) rotate(a=0, v=[0,0,0]) cylinder(r=3, h=3, $fn=25);
*/
	}

	union()
	{
if (pads==1){
	//Mounting holes
	color("red") translate([80,18,-1]) rotate(a=0, v=[0,0,0]) cylinder(r=1.5, h=10, $fn=25);
	color("red") translate([25.5,43.5,-1]) rotate(a=0, v=[0,0,0]) cylinder(r=1.5, h=10, $fn=25);

	//Countersink holes
	color("red") translate([80,18,3]) rotate(a=0, v=[0,0,0]) cylinder(r=3, h=4, $fn=25);
	color("red") translate([25.5,43.5,3]) rotate(a=0, v=[0,0,0]) cylinder(r=3, h=4, $fn=25);
}
	//Spacer pad holes
	color("red") translate([40,30,-1]) rotate(a=0, v=[0,0,0]) cylinder(r=1.5, h=10, $fn=25);
	color("red") translate([60,30,-1]) rotate(a=0, v=[0,0,0]) cylinder(r=1.5, h=10, $fn=25);

    //corner holes to avoid cracks Niels4140
    translate([25.5-3-delta,4+0.5,6+0.5]) rotate([0,90,0]) cylinder(r=1, h=54.5+6+2*delta, $fn=25);
    translate([25.5-3-delta,frame_w+4-0.5,6+0.5]) rotate([0,90,0]) cylinder(r=1, h=54.5+6+2*delta, $fn=25);
	}
}

}

```


[User]
Hi, I'm looking to design a parametric trinket box with a lid that can accept inlay patterns, similar to the ones I've seen on Thingiverse (specifically in the modular coaster collections linked in the description above, though I don't need the AI to design the coaster inserts themselves).  I'd like the box and lid to be generated as separate models.

Here are the specific parameters I want to control:

*   **Box Length:** The external length of the box in millimeters. I'd like to be able to specify this as an integer, likely between 110mm and 200mm. Let's call this `Box_Length`.
*   **Box Width:** The external width of the box in millimeters. Also an integer between 110mm and 200mm. Let's call this `Box_Width`.
*   **Box Depth:** The external depth of the box in millimeters. This will be an integer as well, let's call this `Box_Depth`.
*   **Box Style:** This will be an integer that adjusts the overall thickness and style of the box.  I'm not entirely sure what the math looks like here so I'd like for it to be an integer with a range from 2 to 10. This will affect the radius of the corner fillets and thickness of the walls. This should be named `Box_Style`.

I'd like the design to include a lid that fits snugly into the top of the box, with a lip or edge that overlaps the box for a secure fit. The lid should have a recessed area that's the same size as the modular coaster insert pattern (as described in the Thingiverse links) so I can snap those in.

I also need a way to specify whether I want to generate just the box, just the lid, or both. This will probably be an enum-type variable? `Build_Group`, maybe, with options like `1:BOTH`, `2:BOX`, and `3:LID`.

Finally, I think the design uses a hull operation to create the rounded corners, so that should probably be used for the main structure. I'm not too picky about the exact style otherwise, as long as it's functional and creates a reasonably snug fit. I need the final output to be an .stl file, though I assume the OpenSCAD design will also be created in order to generate it.  I'd like all the components to be within a single SCAD file.

[Assistant]
trinket_box_inlay.scad:
```
// trinket_box_inlay.scad
// library for parametric Trinket Box, Container, Enclosure, Organizer, Storage
// Author: Tony Z. Tonchev, Michigan (USA)
// last update: January 2019

// Length of box exterior (in mm)
Box_Length = 110; //[110:200]

// Width of box exterior (in mm)
Box_Width = 110; //[110:200]

// Depth of box exterior (in mm)
Box_Depth = 50;

// Box style/structure tune
Box_Style = 2; //[2:10]

// Group
Build_Group = 1; //[1:BOTH, 2:BOX, 3:LID]

/* [Hidden] */

TZT_X=Box_Length-8;
TZT_Y=Box_Width-8;
TZT_Z=Box_Depth;
TZT_R=4;
TZT_W=TZT_R/Box_Style+1;
$fn=40;

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

if (Build_Group!=3) translate ([0,Box_Width*0.55,0]) TZT_Container ();
if (Build_Group!=2) translate ([0,-Box_Width*0.55,TZT_W+TZT_R/2]) rotate ([0,180,0]) TZT_Lid ();

module TZT_Lid () {
    difference () {
        union () {
            translate ([0,0,TZT_W]) TZT_Box ([TZT_X,TZT_Y,TZT_R/2,TZT_R,TZT_R/2]);
            TZT_Box ([TZT_X,TZT_Y,TZT_W,TZT_R,TZT_R]);
            translate ([0,0,-TZT_W]) TZT_Box ([TZT_X-2*TZT_W-1,TZT_Y-2*TZT_W-1,TZT_W,TZT_R-TZT_W-0.5,TZT_R-TZT_W-0.5]);
        }
        translate([0,0,4]) cylinder (8,46,49,true, $fn=100);
        translate([0,0,1]) cylinder (3,47.2,47,true, $fn=100);
        translate([0,0,-0]) cylinder (10,45,45,true, $fn=100);
    }
}

module TZT_Container () {
    difference () {
        TZT_Box ([TZT_X,TZT_Y,TZT_Z,TZT_R,TZT_R]);
        translate ([0,0,TZT_W]) TZT_Box ([TZT_X-2*TZT_W,TZT_Y-2*TZT_W,TZT_Z,TZT_R-TZT_W,TZT_R-TZT_W]);
        TZT_Thmb=TZT_W/10;
        for (x=[-1:2:1]) {
            translate ([0,(TZT_Y/2+TZT_R)*x,TZT_Z]) scale ([1,TZT_Thmb,1]) sphere (10);
            translate ([(TZT_X/2+TZT_R)*x,0,TZT_Z]) scale ([TZT_Thmb,1,1]) sphere (10);
        }
    }
}

module TZT_Box (TZT_Sz) {
    hull () {
        for (x=[-1:2:1]) for (y=[-1:2:1]) {
            translate ([TZT_Sz[0]/2*x,TZT_Sz[1]/2*y,0]) cylinder (TZT_Sz[2],TZT_Sz[3],TZT_Sz[4]);
        }
    }
}
```


[User]
Okay, I'm looking to create a set of parametric Lego-compatible roof pieces, similar to the ones described in the provided SCAD code, but I need to generate the code from scratch. I want to be able to define a few key parameters to control the size and shape of these roof pieces.

Here's the basic idea: I need a range of roof transition pieces, specifically, I need to handle 12 different roof piece shapes based on a 'type' parameter (0 to 11). These pieces should be compatible with standard Lego bricks. I'd like to be able to generate all 12 types, as well as any individual piece type. I'd also like to be able to tweak the overall dimensions of the pieces.

Here are the parameters I'd like to control:

*   **`Type`**: An integer selecting which roof piece type to generate. This should be a value between -1 and 11. If `Type` is -1, generate all 12 types (0-11) in a grid layout.
*   **`ShellThickness`**: The thickness of the walls of the roof pieces, expressed in millimeters.
*   **`CellWidth`**: The basic outer dimension of a single cell in the Lego grid unit, in millimeters.
*  **`Height`**: The overall height of the piece, in millimeters.
*   **`NubbinHeight`**: The height of the nubbins on the top of the roof pieces (those that connect to other Lego bricks), in millimeters.
*   **`NubbinDiameter`**: The diameter of the nubbins on the top of the roof pieces, in millimeters.
*   **`NubbinPitch`**: The center-to-center distance between nubbins, in millimeters.
*   **`holeOD`**: The outside diameter of the tubes underneath the roof pieces that connect to the studs on standard Lego bricks, in millimeters.
*   **`StepHeight`**: The height of the bevel or step at the bottom edge of each roof piece, in millimeters.
*   **`cx` and `cy`**: These are internal parameters that are hardcoded to 2 in the reference code. It would be good if these were also user-adjustable as well, controlling the number of 'cells' along each axis.

The code should use the `linear_extrude` and `polygon` OpenSCAD primitives, and include difference operations to create the interiors. The code should create the nubbins on the top, the hollow tubes underneath, and a bevel/step at the bottom of each piece. The various piece types (0 to 11) are formed by combinations of basic shapes (essentially modified trapezoids with the slope on the upper or lower edge) and rotations/intersections and unions. When all types are generated, each should have a label with the corresponding type number so it's clear which is which.

Could you generate an OpenSCAD file (or files) for me that incorporates all of this functionality? I do not need any external libraries, just the standard OpenSCAD language.

[Assistant]
lego_roof.scad:
```
// Parametric Lego Brick-compatible roof pieces
// David O'Connor david@lizardstation.com
// Creative Commons Attribution (CC-BY-3.0) License Applies
// 8 February 2019

Type = 2; // [-1:11]
ShellThickness = 1.2;  //
CellWidth = 7.85; // Brick outer dimension unit size
Height = 9.6;     // Brick Height
NubbinHeight = 2.4;  // Nubbin Height
NubbinDiameter = 4.85;  // Nubbin Diameter
NubbinPitch = 8.00;   // Distance from one nubbin center to the next
holeOD = 6.6;          // Outside diameter on tubes underneath
StepHeight = 2.2; // Bevel at the bottom of each piece

/* [Hidden] */
cx = 2;
cy = 2;
eps = 0.1; // Small value to provide a margin for CSG operations
t = Type;
$fa = 5; $fs = 1;

if (t == -1) {
    for (tt = [0:11]) {
        translate([CellWidth * 4, CellWidth * 3* (5 - tt), 0]) {
            color([1, 1, 0]) union() {
                difference() {
                    main_volume(tt, cx, cy, true);
                    main_volume(tt, cx, cy, false);
                }
                insides(tt, cx, cy);
                nubbins(tt, cx, cy);
            }
            translate([-CellWidth * 2, 0, 0])
            rotate([0, 0, -90])
            color([1, 0, 0])
            linear_extrude(CellWidth * 0.2)
            text(str(tt), valign = "center", halign = "center");
        }
    }
}
else {
    union() {
        difference() {
            main_volume(t, cx, cy, true);
            main_volume(t, cx, cy, false);
        }
        insides(t, cx, cy);
        nubbins(t, cx, cy);
    }
}

module main_volume(type, CellX, CellY, outside) {
    if ((type == 0) || (type == 1)) {
        basic_shape(type, CellX, CellY, outside);
    }

    if (type == 2) {
        intersection() {
            basic_shape(0, 2, 4, outside);
            rotate([0, 0, 90]) {
                basic_shape(0, 2, 4, outside);
            }
        }
    }

    if (type == 3) {
            intersection() {
            basic_shape(0, 2, 4, outside);
            rotate([0, 0, 90]) {
                basic_shape(1, 2, 4, outside);
            }
        }
    }

    if (type == 4) {
            intersection() {
            basic_shape(1, 2, 4, outside);
            rotate([0, 0, 90]) {
                basic_shape(1, 2, 4, outside);
            }
        }
    }

    if (type == 5) {
        union() {
            basic_shape(0, 2, 2, outside);
            rotate([0, 0, 90]) {
                basic_shape(0, 2, 2, outside);
            }
        }
    }

    if (type == 6) {
        union() {
            basic_shape(0, 2, 2, outside);
            rotate([0, 0, 90]) {
                basic_shape(1, 2, 2, outside);
            }
        }
    }

    if (type == 7) {
        union() {
            basic_shape(1, 2, 2, outside);
            rotate([0, 0, 90]) {
                basic_shape(1, 2, 2, outside);
            }
        }
    }

    if (type == 8) {
        intersection() {
            main_volume(5, 2, 2, outside);
            rotate([0, 0, 180]) {
                main_volume(5, 2, 2, outside);
            }
        }
    }

    if (type == 9) {
        intersection() {
            main_volume(6, 2, 2, outside);
            rotate([0, 0, 90]) {
                main_volume(5, 2, 2, outside);
            }
        }
    }

    if (type == 10) {
        intersection() {
            main_volume(2, 2, 2, outside);
            main_volume(7, 2, 2, outside);
        }
    }

    if (type == 11) {
        intersection() {
            main_volume(0, 2, 2, outside);
            rotate([0, 0, 180]) {
                main_volume(6, 2, 2, outside);
            }
        }
    }
}

module basic_shape(type, CellX, CellY, outside) {
    rotate([90, 0, 0]) {

            c = outside == true ? CellWidth : CellWidth - ShellThickness;
            h = outside == true ? Height : Height - 1.4*ShellThickness;
            f = outside == true ? 0 : -10;
            s = outside == true ? StepHeight : StepHeight;
            e = outside == true ? CellY*CellWidth : CellY * CellWidth - 2 * ShellThickness;

        linear_extrude(height = e, center = true) {
            if (type == 0) {
                polygon([ [-c, f], [c, f], [c, h], [0, h], [-c, s] ]);
            }

            if (type == 1) {
                polygon([ [-c, f], [c, f], [c, s], [0, h], [-c, s] ]);
            }
        }
    }
}

module nubbins(type, CellX, CellY) {
    if ((type == 0)  || (type == 6)){
        union() {
            i = 2;
            x = (2 - (CellX+1)*0.5) * NubbinPitch;
            for (j = [1:CellY]) {
                y = (j - (CellY+1)*0.5) * NubbinPitch;
                translate([x, y, Height])
                cylinder(h = NubbinHeight, r = NubbinDiameter * 0.5);
            }
        }
    }
    if ((type == 2) || (type == 9))  {
        translate([0.5*NubbinPitch, 0.5*NubbinPitch, Height]) {
            cylinder(h = NubbinHeight, r = NubbinDiameter * 0.5);
        }
    }

    if (type == 5) {
        translate([0.5*NubbinPitch, 0.5*NubbinPitch, Height]) {
            cylinder(h = NubbinHeight, r = NubbinDiameter * 0.5);
        }
        translate([ 0.5*NubbinPitch, -0.5*NubbinPitch, Height]) {
            cylinder(h = NubbinHeight, r = NubbinDiameter * 0.5);
        }
        translate([-0.5*NubbinPitch, 0.5*NubbinPitch, Height]) {
            cylinder(h = NubbinHeight, r = NubbinDiameter * 0.5);
        }
    }

    if (type == 8) {
        translate([ 0.5*NubbinPitch, -0.5*NubbinPitch, Height]) {
            cylinder(h = NubbinHeight, r = NubbinDiameter * 0.5);
        }
        translate([-0.5*NubbinPitch, 0.5*NubbinPitch, Height]) {
            cylinder(h = NubbinHeight, r = NubbinDiameter * 0.5);
        }
    }
}

module insides(type, CellX, CellY) {
    intersection() {
        translate([0, 0, -eps])
        main_volume(type, CellX, CellY, false);
        {
            translate([0, 0, 0.5*Height]) {
                difference() {
                    union() {

                        x = (1 - CellX*0.5) * NubbinPitch;
                        translate([x, 0, 0]) {
                            cube(size = [ShellThickness, CellY * CellWidth, Height], center = true);
                        }
                        for (j = [1:CellY-1]) {
                            translate([0, y, 0]) {
                                cube(size = [CellX*CellWidth, ShellThickness, Height], center = true);
                            }
                            y = (j - CellY*0.5) * NubbinPitch;
                            translate([x, y, 0]) {
                                cylinder(h = Height, r = holeOD * 0.5, center = true);
                            }
                        }
                    }

                    // Drill the holes
                    union() {
                        for (i = [1:CellX-1]) {
                            x = (i - CellX*0.5) * NubbinPitch;
                            for (j = [1:CellY-1]) {
                                y = (j - CellY*0.5) * NubbinPitch;
                                translate([x, y, -ShellThickness]) {
                                    cylinder (h = Height, r = holeOD * 0.5 - ShellThickness, center = true);
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}

```


[User]
I'm looking to design a router support foot adapter, something that lets me use a specific support foot (like the one from this Thingiverse link: https://www.thingiverse.com/thing:3399941) with different router brands. Basically, the existing foot has a sliding dovetail that needs to fit into a new housing, and this housing then needs to mount onto the rails of the router.

Here are the specific design requirements I have in mind:

**General Shape and Dimensions:**

*   The main body of the adapter should be a rectangular block with rounded edges and a 'shoulder' feature on the top. The shoulder extends beyond the main block on the left and right sides and has an angled profile.
*   The overall length of the main block will be determined by the distance between the router's rail mounting points, plus a bit extra on each side.
*   The height of the adapter will be fixed to a specific dimension and will determine the scale of the shoulder feature.
*   The thickness of the adapter will also be fixed.
*   There should be a cut-out or opening to accommodate the sliding dovetail of the support foot. This cut-out will need to be precisely sized.

**Mounting to Router Rails:**

*   The adapter needs two mounting holes for screws or threaded rods. The center-to-center distance between these holes must be adjustable (a parameter).
*   The mounting holes should be sized for M8 screws or rods.
*   There needs to be an opening/counterbore for the M8 screw heads or nuts. This needs to be sized appropriately for M8 hex heads.
*   The depth of these counterbores will need to be a parameter.
*   The cut-out for the screw head will need to be designed so that I can choose whether the nut side is "inside" (recessed into the adapter) or "outside" (protruding from the adapter).

**Mounting the Support Foot:**

*   There should be a hole for an M6 screw to secure the support foot in place.
*   This hole should be centered in the width of the main body, and located on top of the support foot cut-out/opening.

**Key Parameters:**

I need to be able to adjust these parameters through the customizer:

*   `cutout_precision`: A value to compensate for the tendency of my printer to print cutouts too small.  I'd like to add this to the hole diameters.
*   `nut_pos`:  A string parameter with "inside" or "outside" values for whether the nuts are recessed for the rail screws or not.
*   `thn_adapter`: Thickness of the main block of the adapter.
*   `h_adapter`: Height of the main block of the adapter.
*   `w_foot`: Width of the support foot's sliding dovetail.
*  `thn_foot`: Thickness of the support foot's sliding dovetail.
*   `d_foot_screw`: Diameter of the screw for the support foot (M6).
*   `d_rail_screw`: Diameter of the screws for the router rails (M8).
*   `d_head_rail_screw`: Diameter of the rail screw hex head (flat sides).
*   `thn_head`: Depth/thickness of the rail screw head.
*   `delta_rail`: Center-to-center distance between the rail screw holes.
*   `rounding_radius`: Radius for rounding the edges.

**Libraries:**

I don't anticipate needing any libraries beyond standard OpenSCAD functionality for this design, though it will be important to get those dimensions for the hex nuts right.

I think that's all. Let me know if you have any questions.

[Assistant]
Support_Foot_Adapter.scad:
```
$fa=1*1;
$fs=0.25*1;

// compensate cut-out precision: my printer tends to print cut-outs 0.4 mm too small. Add this to value to cut-out, e.g. screw boring. Adjust this setting according to the precision of your printer
cutout_precision = 0.4;

// side on which to place for opening for nut
nut_pos = "outside"; // [inside, outside]

// thickness of holder
thn_adapter = 15;

// height of holder on flat part, mid/shoulder part is scaled accordingly
h_adapter = 18;

// width of foot (width of foot slider cut-out)
w_foot = 25;

// thickness of foot (depth of foot slider cut-out)
thn_foot = 8;

// foot holder screw diameter: M6
d_foot_screw = 6;

// rail screws diameter: M8
d_rail_screw = 8;

// rail screws: diameter of M8 hex head (flat sides)
d_head_rail_screw = 12.7; // 10.4;

// thickness of screw head / opening depth
thn_head = 5;

// center-center distance between openings for rail screws. Adjust this according to your router.
delta_rail = 84;

// rounding
rounding_radius=2;

l_adapter = delta_rail + 20;
thn_adapter_mod = thn_adapter-2*rounding_radius;
h_adapter_mod = h_adapter-1*rounding_radius;  // only 1 due to reduced shoulder offset
z_rail = h_adapter_mod / 2;

// compensate for cut-out precision
d_foot_screw_mod = d_foot_screw + cutout_precision;
d_rail_screw_mod = d_rail_screw + cutout_precision;
d_head_rail_screw_mod = d_head_rail_screw + cutout_precision;
w_foot_mod = w_foot + cutout_precision;

difference() {
    minkowski() {
        union() {
            translate([-l_adapter/2, 0, 0])
                cube([l_adapter, h_adapter_mod, thn_adapter_mod]);

            shoulder();
        }
        sphere(rounding_radius);
    }

    // foot cut-out
    translate([-w_foot_mod/2, -h_adapter_mod, thn_adapter_mod+rounding_radius-thn_foot])
        cube([w_foot_mod, h_adapter_mod*3, thn_foot]);

    if (nut_pos == "inside") {
        rail(thn_adapter-rounding_radius-thn_head);
    } else {
        rail(-rounding_radius);
    }

    translate([0, h_adapter_mod, -h_adapter])
        cylinder(h_adapter*2, d=d_foot_screw_mod);
}

module shoulder() {
    translate([0,h_adapter_mod,0]) {
         linear_extrude(thn_adapter_mod)
            polygon(points = [[-w_foot_mod/2-10,0], [-w_foot_mod/2-5,h_adapter_mod/2],
                              [w_foot_mod/2+5,h_adapter_mod/2], [w_foot_mod/2+10,0]]);
    }
}

module rail(y_rail) {
    translate([0, z_rail, y_rail]) {

        translate([delta_rail/2, 0, 0]) {
            hex_nut(d_head_rail_screw_mod, thn_head);
            screw();
        }
        translate([-delta_rail/2, 0, 0]) {
            hex_nut(d_head_rail_screw_mod, thn_head);
            screw();
        }
    }
}

module screw() {
    screw_len = 100;
    translate([0, 0, -screw_len/2]) {
        cylinder(screw_len, d=d_rail_screw_mod);
    }
}

module hex_nut(d_head_flat, thn_head) {
    r = (d_head_flat/2) / cos(30);
    linear_extrude(thn_head)
        polygon(points = [[r, 0], [r * cos(60), r * sin(60)],
                          [r * cos(120), r * sin(120)],
                          [r * cos(180), r * sin(180)],
                          [r * cos(240), r * sin(240)],
                          [r * cos(300), r * sin(300)]]);
}
```


[User]
Hey! I'm trying to design a parametric model for a Korean dojang (a personal seal/stamp) in OpenSCAD, and I'm a little stuck. I'd love for your help! I have a few specific ideas about how I want it to work.

First off, I want the user to be able to choose between a square or a circular dojang. There should be a variable for this. Also, the user needs to specify the font used for the text on the dojang. I'm thinking we should assume that it's a system font, like "Arial:style=Bold" or "NanumMyeongjo:style=Bold".

Then, there's the text itself. We'll need two text input variables: one for the main name and a second for an optional additional line (if they don't want the second line, it should be an empty string). The main name will be centered, and if there's a second line, it should be centered beneath it. The text needs to be extruded and reversed so it stamps properly. There should be a variable for the text height.

The user should also be able to specify the overall width of the dojang. For circular dojangs this will be the diameter. For square dojangs, this will be the length of a side. We'll also need a height variable for the dojang body.

A final couple of parameters will be a border thickness, and the ability to resize the text area (independent X and Y resize parameters, with 0 meaning no resize.) Also, an optional Y offset for the two lines of text. If there's only one line, it should be 0. If there are two lines of text, it could be something like 5mm to push the whole text block upwards a little bit.

So, to summarize, I need to be able to specify:

*   **Type:** Square (1) or Circular (2)
*   **Font:** System font name (like "Arial:style=Bold")
*   **Name1:** Main text for the dojang.
*   **Name2:** Optional secondary line of text (empty string if not used)
*   **Text Height:** The height of the extruded text.
*   **Width:**  Overall width or diameter of the dojang.
*   **Height:** Height of the dojang body.
*   **Border:** Border thickness around the edge.
*   **XRESIZE:** Text resize value for the X direction (0 to disable resize)
*   **YRESIZE:** Text resize value for the Y direction (0 to disable resize)
*   **YOFFSET:** Y offset for the text, if there are two lines.

I think the design will require a few steps: create the base shape (square or circle), create the inner void, then create the extruded text, making sure that the text is reversed.

It seems like it wouldn't require any external libraries, but if you think that would help, I'm open to suggestions.

Let me know if you have any questions, and thanks for the help!

[Assistant]
Dojang.scad:
```
$fn = 90;

// Type of dojang: 1 - Square, 2 - Circular
TYPE = 2;

// Font to use. I recommend using a bold font so it prints better. The font will be system dependent. On Ubuntu 18.04, "NanumMyeongjo:style=Bold" is a good font
FONT = "NanumMyeongjo:style=Bold";

// Name to put on Dojang. The name will be centered and cropped to the size of the Dojang
NAME1 = "정민주";

// 2nd line of name. Optional. Set to "" to exclude.
NAME2 = "";

// Text Height
TH = 3;

// Width of the Dojang. Diameter if a circular dojang. Length of a side if its square
W = 30;

// Height of Dojang.
H = 45;

// Border Thickness
BORDER = 3;

// X Resize - Set to resize value for X direction, W-3*BORDER is a good value. Set to 0 to not resize
XRESIZE = W-3*BORDER;

// Y Resize - Set to resize value for Y direction, W-3*BORDER is a good value. Set to 0 to not resize
YRESIZE = W-3*BORDER;
//YRESIZE = 0;

// Y Offset - Set to 0 if only 1 line name. Set to an appropriate offset in mm if 2 line name. 5 is a good default.
YOFFSET = 0;
//YOFFSET = 5;

module name () {
    mirror([1,0,0])
        translate([0,YOFFSET,H-TH/2-0.01])
        resize([XRESIZE,YRESIZE,TH])
        linear_extrude(height = TH+0.01, center = true, convexity = 10, twist = 0) {
            text(NAME1, halign="center", valign="center", font=FONT);
            if (NAME2 != "") {
                translate([0,-15,0])
                    text(NAME2, halign="center", valign="center", font=FONT);
            }
        }
}

name();
if (TYPE == 1) { // Square stamp
    translate([0,0,(H-TH)/2]) cube([W, W, H-TH], center=true);
    difference () {
        translate([0,0,H/2]) cube([W, W, H], center=true);
        translate([0,0,H/2]) cube([W-BORDER, W-BORDER, H*1.5], center=true);
    }
} else if (TYPE == 2) { // Circular stamp
    translate([0,0,(H-TH)/2]) cylinder(d=W, h=H-TH, center=true);
    difference () {
        translate([0,0,H/2]) cylinder(d=W, h=H, center=true);
        translate([0,0,H/2]) cylinder(d=W-BORDER, h=H*1.5, center=true);
        }
}

```


[User]
I'm looking to create a customizable heart-shaped planter, and I'd like the design to be parametric so I can easily change its dimensions. I need to be able to specify the height, the width of the bottom, the width of the top, and the wall thickness. Also, I'd like an optional drain hole at the bottom with a configurable diameter. I also want the option to slant the top of the planter from back to front, by specifying a slant angle, and I need to specify the height of an optional saucer. Can you generate the necessary OpenSCAD files?

Specifically, here's what I want:

*   A main planter body that's a tapered heart shape (wider at the top, narrower at the bottom).
*   The ability to set the overall `height` in millimeters.
*   The ability to set the `bottom` width in millimeters.
*   The ability to set the `top` width in millimeters.
*   The ability to set the `wall` thickness in millimeters.
*   An optional `hole` diameter for a drain hole at the bottom (0 for no hole).
*   An optional `slant` angle in degrees to slant the top of the planter.
*   An optional `saucerHeight` parameter in millimeters for the height of the saucer.

I'd like to be able to generate just the planter, just the saucer, or both together, so please include a parameter to switch between the parts being generated. The main planter body should be a hollowed-out heart shape, with the wall thickness I set. I'd prefer if the design uses the `minkowski()` operation with a small sphere to round the edges of the planter, rather than using an expensive `hull()` operation.

I would also like to include a small cylindrical decorative tag, or stick, with a heart shape on the front of it. I will provide some parameters in a bit to determine the dimensions of the stick, but please start with a default for me.

I'm not using any external libraries, so everything should be written in standard OpenSCAD.

[Assistant]
heart-planter-2.scad:
```
// heart-planter
// lucina
// 2019-02-08
/* [planter settings] */
// which part
whichPart = "planter";  //[planter, saucer, both]
// height in mm
height = 70;  //[20:5:200]
// bottom width in mm
bottom = 60;   //[20:5:200]
// top width in mm
top = 80;   //[20:5:200]
// wall size in mm
wall = 1.2; //[.6:.1:3]
// drain hole size in mm (0=no hole)
hole = 6;   //[0:1:10]
// slant top angle
slant = 0; // [0:40]
// saucerHeight in mm
saucerHeight = 8;  //[8:30]

/* [Hidden] */
$fn = 60;
x = 0; y = 1; z = 2;
bb = .66667 * bottom;
tt = .66667 * top;

module fcube(x, y, z, rad) {
   translate([rad-x/2, rad-y/2, rad-z/2])
      minkowski() {
         cube([x-2*rad, y-2*rad, z-2*rad]);
         sphere(rad);
      }
}
module taperHeart(t, b, hh) {
   union() {
      hull() {
         cube([b, b, .001], center=true);
         translate([0, 0, hh])
            cube([t, t, .001], center=true);
      }
      hull() {
         translate([0, b/2.0, 0])
            cylinder(h=.001, d=b);
         translate([0, t/2.0, hh])
            cylinder(h=.001, d=t);
      }
      hull() {
         translate([b/2, 0, 0])
            cylinder(h=.001, d=b);
         translate([t/2, 0, hh])
            cylinder(h=.001, d=t);
      }
   }
}
module heart(size, hh) {
//   translate([-.25*size, -.25*size, 0])
   union() {
      cube([size, size, hh]);
      translate([0, size/2.0, 0])
         cylinder(h=hh, d=size);
      translate([size/2.0, 0, 0])
         cylinder(h=hh, d=size);
   }
}
module slantedPlanter() {
   // planter
   rotate([0, 0, -45])
   translate([0, .57*top, height])
      rotate([slant, 0, 0])
         difference() {
            rotate([-slant, 0, 0])
             translate([0, -.57*top, -height])
               rotate([0, 0, 45])
                 // hollow and drain hole
                 difference() {
                     taperHeart(tt, bb, height);
                     union() {
                        translate([0, 0, wall])
                           taperHeart(tt-2*wall, bb-2*wall, height);
                        translate([.125*bb, .125*bb, -wall])
                           cylinder(h=3*wall, d=hole);
                     }
                  }
            // for slanting
            translate([0, 0, height/2])
            cube([1000, 1000, height], center=true);
         }
}
module planter() {
  difference() {
      taperHeart(tt, bb, height);
      union() {
         translate([0, 0, wall])
            taperHeart(tt-2*wall, bb-2*wall, height);
         translate([.125*bb, .125*bb, -wall])
            cylinder(h=3*wall, d=hole);
      }
   }
   // top band
   translate([0, 0, height-4])
      difference() {
         taperHeart(tt, tt, 4);
         translate([0, 0, -2])
            taperHeart(tt-2*wall, tt-2*wall, 8);
      }
}
module saucer() {
   intersection() {
      cylinder(h=saucerHeight, d=max(top, bottom)*3);
      difference() {
         taperHeart(tt+4, bb+4, height);
         translate([0, 0, wall])
            taperHeart((tt+4)-2*wall, (bb+4)-2*wall, height);
      }
   }
}
module doPlanter() {
   if ( slant == 0 )
      planter();
   else
      slantedPlanter();
}
if ( whichPart == "planter" ) {
   doPlanter();
}
if ( whichPart == "saucer" )
   saucer();
if ( whichPart == "both" )
   union() {
      doPlanter();
      translate([max(top, bottom)+3, 0, 0])
         saucer();
   }
if ( whichPart == "stick" ) {
   heart = [40, 40, 3];
   stick = [4, 80, 3];
   rr = heart[z]/2 - .0001;

   rotate([0, 0, -135])
      minkowski() {
         heart(heart[x]*.6667-2*rr, heart[z]-2*rr);
         sphere(rr);
      }
   translate([0, -stick[y]/2-heart[y]+8, 0])
      fcube(stick[x], stick[y], stick[z], stick[z]/2-.0001);
}

```


[User]
Hey, I'm looking to design a customizable ruler for my 2nd-grade class. I'd like it to be a parametric OpenSCAD design so kids can tweak it. Here's what I have in mind:

**Basic Ruler:**

*   It should be a flat, rectangular ruler, with a main body and a beveled edge on one side.
*   The overall length needs to be adjustable, but I'd like to set a default of 203mm (which will give a usable 20cm measurement scale).
*   The main body of the ruler should have an adjustable width, but a default of 28mm would work.
*   The beveled edge should have its own adjustable width, defaulting to 5mm.
*   The total height (thickness) of the ruler should also be adjustable, with a default of 4mm.
*   The bevel itself should have an adjustable height, defaulted to 1mm, and must be less than or equal to the total ruler height, or else we might not see the lines or text.
*   A small hole for a keychain should be added at one end. It should have an adjustable radius, and a default of 2.5mm works.

**Markings:**

*   I need lines marking each centimeter (10mm). These lines should start 3mm from each end of the ruler.
*   Also, I would like lines marking each millimeter, but not as bold as the cm lines. They should start 3mm from each end of the ruler.
*   I'd like lines for 5mm as well, a bit longer than the 1mm lines.
*  The lines should be engraved, meaning the cut into the surface, so I need a LineDepth (defaulting to 0.4mm) and LineWidth (defaulting to 0.5mm). The LineWidth should probably be a bit bigger than the printer's nozzle.
*   The lines on the beveled edge should be angled at a rate that the difference between the height of the bevel to the height of the main ruler, divided by the width of the bevel.

**Text and Numbers:**

*   The ruler should have numbers indicating the cm markings. These should be positioned above the ruler lines and should have an offset from the actual markings.  I was thinking an offset of -2mm should look good, but I need this to be editable.
*   I need to be able to add custom text to the ruler.
*   I need parameters for the font size, and the text height. I'd like a default font size of 7.4mm and text height of 0.6mm.
*   The text and number height needs to be a multiple of the layer thickness.
*   I would like to have offsets so I can control the text's position, horizontally (TextX) and vertically (TextY) from the edge of the main ruler. Defaults of 2mm for both should be fine.

**Important Notes:**

*   I want to use the "Write.scad" library to handle the text. It is available on Thingiverse and should be in a "libraries" folder that openSCAD will find.  I've included the path `use <write.scad>` and `use <write/Write.scad>` to the file as an example.
*   All units should be in millimeters.
*   I think everything should be customizable (within reason), so using parameters is a must.

I think that covers it. Could you generate the necessary OpenSCAD files for this? I'm mostly looking for the main `.scad` file, but any supporting files are welcome. Let me know if you have any questions!

[Assistant]
ruler_4_kids_20cm-web.scad:
```
//customizable ruler by Mark G. Peeters CC-BY-SA (original file by Stu121 https://www.thingiverse.com/thing:109739)
//version ruler_4_kids_20cm is for 1 cm ruling only
//if you are using openSCAD then you are cool, and make sure you have downloaded "Write.scad" from here http://www.thingiverse.com/thing:16193 and save it in your libraries directory
use<write.scad>
use<write/Write.scad>

//NOTE: ALL units are in millimeters (mm) even font sizes
RulerText="Your Imagination can not be measured";

//size for the letters and numbers-still in millimeters
FontSize=7.4;//do not go smaller than 6mm

// radius for key chain hole, 2.5mm seems good, zero for no hole
HoleRadius = 2.5;

/* [Hidden] */

//don't make ruler longer than your print bed,also the "measurable scale lenght" is less because the scale starts and stops 3mm before each end
RulerLength=203;//[10:300]

//- the part with numbers and letters. NOTE: ruler total width = RulerWidth + BevelWidth
RulerWidth=28;//[15:35]

//- the part with the lines on it
BevelWidth=5;//[3:10]

NumberSize=5;

// how tall are letters and numbers , suggest this is a mulitple of layer thickness that will be used for slicing
TextHeight=.6;

/* [Advanced] */

//- thickness of the ruler body- NOTE! RulerHeight>=BevelHeight !! you will not see letters or rulings if you make the BevelHeight larger that the ruler body. they can be equal.
RulerHeight=4;//[1:7]

//- thickness of scale side of ruler. NOTE! must be less than or equal to RulerHeight!! ALSO make sure BevelHeight>LineDepth or else you will get a comb edge ruler
BevelHeight=1;//[1:7]

//how deep are lines into ruler body, suggest mulitple of layer's thickness used for slicing NOTE: if you do not want a comb then make sure BevelHeight>LineDepth so lines don't cut thought bottom of bevel
LineDepth=0.4;

//how wide are lines into ruler body, consider just a tiny bit bigger the Nozzle diameter
LineWidth=.5;//[.2,.3,.4,.5,.6]

//for centering text side to side, this is starting x displacement from edge, make zero for flush with side edge
TextX=2;

//for centering text up and down, this is starting y displacement from top, make zero for flush with top, negative for over top, it can look cool if you don't go crazy
TextY=2;

//use to center the numbers over the rule lines
NumberOffset=-2;//[0:3]

/* [Hidden] */

difference(){
hull(){
//make ruler top part - box
translate([0,0,0]) cube([RulerLength,RulerWidth,RulerHeight]);

//make ruler bottom part - bevel
translate([0,-BevelWidth,0])  cube([RulerLength,1,BevelHeight]);
//beveled bottom half

}

//major lines one per cm, starting $ Stopping 3mm from end
for (i=[0:10:(RulerLength-2)]){
translate([i+1,-BevelWidth,BevelHeight-LineDepth]) rotate([atan((RulerHeight-BevelHeight)/BevelWidth),0,0]) cube([LineWidth,BevelWidth,LineDepth+0.2]);
}
//minor lines one per mm
*for (i=[0:1:RulerLength-4]){   //embosed ruler lines
translate([i+1,-BevelWidth,BevelHeight-LineDepth]) rotate([atan((RulerHeight-BevelHeight)/BevelWidth),0,0]) cube([LineWidth,(BevelWidth/2),LineDepth]);
}

//minor lines one per 5mm
*for (i=[0:5:RulerLength-4]){   //embosed ruler lines
translate([i+2,-BevelWidth,BevelHeight-LineDepth]) rotate([atan((RulerHeight-BevelHeight)/BevelWidth),0,0]) cube([LineWidth,(BevelWidth/2),LineDepth]);
}

//add key hole ring
translate([(RulerLength)-(HoleRadius*1.7),(RulerWidth-(HoleRadius*1.7)),-1]) cylinder(h=RulerHeight+2,r=HoleRadius,$fn=20);

}

// write the numbers above markings on the ruler
for (i=[10:10:RulerLength-2]){
if (i > 99){
translate([i+NumberOffset-2,1,RulerHeight]) color("blue")write(str(i/10),h=NumberSize,t=TextHeight);
}
else
translate([i+NumberOffset,1,RulerHeight])color("blue") write(str(i/10),h=NumberSize,t=TextHeight);
}
translate([1,1,RulerHeight])color("blue") write("cm",h=NumberSize,t=TextHeight);
//add personalized text
translate([TextX,(RulerWidth-FontSize)-TextY,0]) color("red") write(RulerText,h=FontSize,t=TextHeight+RulerHeight);

```


[User]
I'd like a parametric OpenSCAD design for a micro SD card adapter mount for an Alfawise U30 3D printer. I need it to be able to mount on either the left or right side of the printer frame, depending on where the LCD is mounted.

The design should essentially be a remix of the existing mount by normandie-xtrem (Thingiverse thing 3393874), but I need the design to be fully parametric to accommodate different SD card adapter heights. The original design used a fixed height, but I found I needed a slightly different height for my specific adapter.

Here's the breakdown of the requirements:

*   **Mounting Sides:** The design needs to be configurable to mount on either the left or right side of the U30 frame. There should be a variable to switch between the sides.
*   **SD Adapter Height:** There should be a parameter that defines the height of the SD card adapter slot. This will allow for variations in the physical adapter.
*   **Base Structure:** The base structure should be a rounded rectangular box with a mounting block that extends out towards the printer frame. This block is the key part that gets flipped for left or right mounting.
*   **Mounting Hole:** It should have two mounting holes for attaching to the printer.
*   **SD Card Slot:** The slot for the SD card adapter should be a rectangular cutout going through the base structure.
*   **Label:** The word "U30" should be displayed as part of the design, just like in the original.
*   **Libraries:** I'm aware you'll need to include the `MCAD/boxes.scad` library for creating the rounded box, and a simple `utils/build_plate.scad` library to draw a build plate.

Basically, I need a fully parameterized version of this existing design that I can easily customize for my specific hardware. Thanks!

[Assistant]
U30_SDcard_Adapter.scad:
```
//----------------------------------------------------------------------------
//	Filename:	U30_SDcard_Adapter.scad
//	Author:		Robert H. Morrison
//	Date:		Thursday, 07 Feb 2019
//
//	This is a recreation of the Alfawise U30 micro SD Card Adapter mount
//  (https://www.thingiverse.com/thing:3393874) by normandie-xtrem
//  (https://www.thingiverse.com/normandie-xtrem) that makes an adapter
//  mount that can be mounted on the left or right hand sides of the U30.
//
//----------------------------------------------------------------------------

use <MCAD/boxes.scad>
use <utils/build_plate.scad>

Mount = -1; //[-1:Right,1:Left]
SD_Adapter_Height = 7.00;

//---[ Build Plate ]----------------------------------------------------------
build_plate(3,100,100);

/* [Hidden] */
h = 36;

translate([0,0,18])
{
    difference()
    {
        union()
        {
            translate([-3.5,9,h / 2 + 0.3])
                rotate([0,0,-90])
                    color([0,0,0])
                        linear_extrude(height=0.6,center=true,convexity=10,twist=0)
                            text("U30","Helvetica:style=Condensed Bold",size=7);

            roundedBox([10,35,h], 2, true, $fn=100);

            translate([12.9,-10*Mount,0])
                cube([16,10,h], true);
        }

        translate([-h,Mount*(-h-12),0])
            rotate([0,90,0])
                color([1,0,0])
                    cylinder(2*h,d1=66,d2=66,true,$fn=600);

        color([0,1,0])
            cube([2.5,50,22.5], true);

        translate([0,Mount*-2,0])
            color([0,0,1])
                cube([SD_Adapter_Height,35,25], true);

        translate([15,h/2,5.5-h/2])
            rotate([90,0,0])
                color([1,0,0])
                    cylinder(h,d1=5.5,d2=5.5,true,$fn=100);

        translate([15,h/2,h/2-10.52])
            rotate([90,0,0])
                color([1,0,0])
                    cylinder(h,d1=5.5,d2=5.5,true,$fn=100);

    }
}
```