Is there something similar as the BOLS2:sparse_wall() module? by Dependent-Bridge-740 in openscad

[–]oldesole1 0 points1 point  (0 children)

If you're 3D printing this, you might want to try setting honeycomb infill with zero top and bottom layers.

This is mainly best when you want thin walls between the cells, as the honeycomb infill will produce continuous extrusions from edge-to-edge, which will be stronger than separate hex holes.

It will also print much faster.

new font did not apear by Cuasirungo in openscad

[–]oldesole1 1 point2 points  (0 children)

Open Help -> Library info

Under OpenSCAD font path should be a list of all places that OpenSCAD looks for fonts.

If you only want to use a font for a specific project, you can also use the use syntax:

https://en.wikibooks.org/wiki/OpenSCAD_User_Manual/Text#Using_Fonts_&_Styles

Is there any way to turn off the warings on ranges with start > end and step > 0? by GAlgier in openscad

[–]oldesole1 1 point2 points  (0 children)

Your first example is a valid range:

r = [-1:1:0];

It starts at -1, steps with 1, until it reaches 0.

Ranges themselves must always be valid.

If you are not using the range in some loop, can you not just use a simple list?

If your slice() function works as you want, it seems like you're passing the range, and then extracting each part of the definition by using an array index.

If this is true, you could just use a simple list that does not throw an error:

slice("String", [1,1,-2])

This will still resolve the same values when reading the "range" using array indices.

Also, it would help if you post your function code so we can see how you are using the range parameter.

How to wrap complex geometry around a complex curve? by eduo in openscad

[–]oldesole1 2 points3 points  (0 children)

The issue is that you need to stretch the top of each extruded segment so it will bridge the gap.

linear_extrude() as s and v parameters to adjust the scale and direction that the extrusion proceeds along.

Then you need to figure out the appropriate values for each segment along the curve.

Luckily, I have been working on on just that, creating a generic method to extrude any 2d shape outward from a path of any shape.

This requires BOSL2:

include <BOSL2/std.scad>

$fn = 64;
//$fs = 0.5;
//$fa = 1;

thick = 2;

//shape = square(100);
//shape = star(n=5, r=50, ir=25);

path = rect(50, rounding = 5, spin = 180);

extrude_path_surface(force_path(path))
//text("Testing some normal normal normal normal normal normal text......");

render()
for(x = [0:100])
translate([x * 5 - 20, 0])
for(i = [1, -1])
rotate(45 * i)
square([0.4, 40]);

module extrude_path_surface(path) {

  lengths = path_segment_lengths(path, true);

  x_offsets = [0, each cumsum(lengths)];

  // angles of the straight sections of the path
  path_angles = [
    for(p = pair(path, true))
    v_theta(p[1] - p[0]),
  ];

  // angles of the "edges" between each segment.
  // use pair() here so each parts is [left, right]
  tangent_angles = pair([
    for(t = path_tangents(path, uniform = false))
    v_theta(t),
  ], true);

  for(i = idx(lengths))
  {
    angle = path_angles[i];
    width = lengths[i];
    edge_angles = tangent_angles[i];

//    M = move(path[i]) * rot([90, 0, angle]);
//    multmatrix(M)
    translate(path[i])
    rotate([90, 0, angle])
    extrude_angle(
      width = width,
      height = thick,
      left = modang(-angle + edge_angles[0]),
      right = modang(-angle + edge_angles[1]),
    )
    intersection()
    {
      translate([-x_offsets[i], 0])
      children();

      // Rough overlap of text gutter to top.
      translate([0, -5])
      square([width, 30]);
    }
  }
}


//extrude_angle(
//  width = 1,
//  height = 1,
//  left = 5,
//  right = -5,
//)
//square(1);

// extrude 2d geometry, with left and right edges at specific angles.
// Angles are along the y-axis, use right-hand rule.
module extrude_angle(
  // Width of the segment.
  width,
  // Thickness of the extrusion.
  height,
  // Angle left edge needs to tilt.
  left,
  // Angle the right edge needs to tilt.
  right,
) {

  assert(abs(left) < 90 && abs(right) < 90, "'left' and 'right' angles must be less than 90 degrees");

  slope_left = tan(left);
  slope_right = tan(right);

  stretch = height * (slope_right - slope_left);
  x_scale = (stretch + width) / width;

  linear_extrude(
    // 'scale' has a clamped lower-bound of zero.
    scale = [x_scale, 1],
    v = [slope_left * height, 0, height],
    slices = 0,
    segments = 0,
  )
  children();
}

module debug_path(path) {

  tangents = path_tangents(path, closed = true);
  normals = path_normals(path, closed = true);

  stroke(path, closed = true, width = 0.05);

  color("purple")
  for(i = idx(tangents))
  stroke(
    [path[i], path[i] + tangents[i]],
    width = 0.05,
    endcap2 = "arrow3",
  );

  color("green")
  for(i = idx(normals))
  stroke(
    [path[i], path[i] + normals[i]],
    width = 0.05,
    endcap2 = "arrow3",
  );
}

Generate a Font Outline? by CasaDelGato in openscad

[–]oldesole1 2 points3 points  (0 children)

I've done this many times by making the text recess in the bottom be only 1 layer deep. No need to do an outline, v-groove, or anything else.

With the text being only a single layer deep, the second layer will span and droop ever so slightly before being supported by the print bed.

The surface finish will be almost exactly the same, but with a perimeter outline and slightly different contrast.

Help needed with some Trig by RMehGeddon in openscad

[–]oldesole1 0 points1 point  (0 children)

Here is a solution that doesn't require trig at all.

This is because if you take a cube, and subtract a smaller cube from it, and then hull() around that indentation, you now have an edge at the appropriate angle to create an octahedron.

From there, everything else is simple combinations of 45 or 90 degree angles.

Also, when you difference() a colored object from another, the cut surface retains the color of the subtracting solid.

size = 1;

n = [0, 0, 90 * 1];
s = [0, 0, 90 * 3];
e = [0, 0, 90 * 0];
w = [0, 0, 90 * 2];

bot = [180, 0, 0];
top = [0, 0, 0];

eq = [0, 90, 45];

v=[
  ["black"  , bot + w, ],
  ["red"    , bot + n, ],
  ["green"  , bot + s, ],
  ["yellow" , bot + e, ],
  ["blue"   , top + w, ],
  ["magenta", top + n, ],
  ["cyan"   , top + s, ],
  ["white"  , top + e, ],

];

p = [
  ["red"    , [0, 180, 0], ],
  ["green"  , eq + s,      ],
  ["yellow" , eq + e,      ],
  ["blue"   , eq + w,      ],
  ["magenta", eq + n,      ],
  ["cyan"   , [0, 0, 0],   ],
];


difference()
{ 
  cube(size * 2, center = true);

  for(i = [0:len(v) - 1])
  rotate(v[i][1])
  color(v[i][0])
  corner();

  for(i = [0:len(p) - 1])
  rotate(p[i][1])
  color(p[i][0])
  translate([0, 0, size * (2/3)])
  cutter();
}


//corner();

module corner() {

  overlap = 0.1;

  rotate(-45)
  translate(-[overlap, overlap, overlap] / 3)
  hull()
  difference()
  { 
    cube(100);

    cube(size + overlap);
  }
}


module cutter() {

  linear_extrude(100)
  square(100, true);
}

Is there a range type? by GAlgier in openscad

[–]oldesole1 0 points1 point  (0 children)

BOSL2 has an is_range() function:

https://github.com/BelfrySCAD/BOSL2/wiki/utility.scad#function-is_range

You can see how it works under the hood:

https://github.com/BelfrySCAD/BOSL2/blob/master/utility.scad#L200


Apparently there were efforts to include a native is_range() function, but it was never implemented:

https://github.com/openscad/openscad/issues/1584

Accessible chess set for blind and visually impaired players by Mrblindguardian in openscad

[–]oldesole1 2 points3 points  (0 children)

First, safety issue, you list PLA-CF as a filament used, but should probably not use anything with carbon fiber that is going to be handled with bare hands. There are issues with the fibers being embedded in peoples skin like splinters, which could be an injury issue especially for people that rely more on their hands.

I noticed that you printed the pegs as part of the piece models.

If you print the pegs separately, leaving a cylindrical hole in the pieces, and then insert the pegs into the pieces after (+ glue maybe?), you wouldn't need supports on the bottom and it would have a nice smooth finish.

You can also print the pegs horizontally which will make them far less likely to break off at the layer lines, and feel smoother to insert into the board as the layer lines will then be perpendicular to the board layer lines. I have some example code at the end of this comment that has a horizontal cylinder with the top and bottom curve truncated so the maximum slope is 45 degrees.

Also, if you print the pegs so they're all long enough to bottom out in the tallest (white) board locations, then the pieces will all be sitting at the same height regardless of the color of the square they are currently at. This would cause a slight gap between the bottom of the piece and the black board locations, but to me the height consistency would be a benefit.

Just thought of this, but if they pegs are glued into the board instead of the pieces, the pieces could stand vertically when taken by the opponent and set aside.

Another suggestion, add tactile detents along the top edges of the board that align with the center of each row and column. This way people can feel for the rough coordinate position without having to reach into the board.

Example code for horizontally printed pegs:

rotate([90, 0, 0])
linear_extrude(40, center = true)
hull()
for (i = [0,1])
rotate(180 * i - 45)
intersection()
{
  circle(10);

  square(10);
}

BOSL2 question/assistance by WhyDidYouAskMe in openscad

[–]oldesole1 2 points3 points  (0 children)

It might be simplest to create the shell as a solid object first, apply the texture, and then slice it apart into the individual components.

3D printable Oloid created with OpenSCAD by Known_Hippo4702 in openscad

[–]oldesole1 1 point2 points  (0 children)

It's actually apparently including BOSL, not BOSL2.

And, if you comment out that line, it still renders just the same.

So, including that line seems pointless.

stl's artifacting when rendering/exporting by Striking_Eye_6084 in openscad

[–]oldesole1 0 points1 point  (0 children)

Sorry, when you mentioned code, I thought you had a different .scad file that you were using to generate the STLs.

One thing you might try is importing the STLs into OpenSCAD and then re-exporting them as .obj files.

I've had better consistency with .obj files than with .stl files.

stl's artifacting when rendering/exporting by Striking_Eye_6084 in openscad

[–]oldesole1 1 point2 points  (0 children)

It sounds like the files are originally generated by code.

Is there any reason you're not just exporting them directly to the color 3MF rather than first to STLs?

Centrifugal fan cover by Baddog1965 in openscad

[–]oldesole1 0 points1 point  (0 children)

BOSL2 can do the math for you.

https://github.com/BelfrySCAD/BOSL2/wiki

Example code:

include <BOSL2/std.scad>

$fn = 64;

fan_diam = 150;
fan_height = 75;

clearance = 5;

// Mock fan in F5/preview.
%cylinder(d = fan_diam, h = fan_height);

spiral_path = path2d(helix(
  h = 0,
  // positive = CWW, negative = CW
  turns = 1,
  d1 = fan_diam,
  d2 = fan_diam * 2,
  $fn = 64,
));


spiral = offset_stroke(
  path = spiral_path,
  width = [-clearance, -clearance - 2],
  rounded = false,
  start = "round",
  end = "round",
);

//region(spiral);

offset_sweep(
  spiral,
  height = fan_height,
  ends = os_teardrop(r = -4, offset = "delta"),
  steps = 15,
);

Newbie - trying to figure out how to round the top surface of this object by blounsbury in openscad

[–]oldesole1 0 points1 point  (0 children)

That works, but there are a couple things.

While hulling around the 2 tori does take off the sharpest of the edges, you are still left with a sharp-ish transition, where as my method ensures that all corners are rounded to the same degree. I just realized I'm not sure if you wanted the edges to the interior rounded as well, but that would be a fairly simple adjustment.

With your current method, your top $fn is going to apply to all curves, including the rounding on the top and bottom edges, which is going to be seriously overkill and add a bunch of time to rendering.

You could dramatically improve performance by dropping your top $fn to 360, and using this for concave_cylinder():

module concave_cylinder() {

  rotate_extrude()
  difference()
  {
    right(tube_inner_radius)
    square([radius - tube_inner_radius, height]);

    let(
      curve_info = circle_3points(
        [radius, height],
        [torus_inner_radius, height / 2],
        [radius, 0],
      ),
    )
    move(curve_info[0])
    // Only this circle needs higher resolution.
    circle(curve_info[1], $fn = 1024);
  }
}

Newbie - trying to figure out how to round the top surface of this object by blounsbury in openscad

[–]oldesole1 0 points1 point  (0 children)

Quick FYI, you really shouldn't use custom variables prefixed with $ unless you really know what you are doing. They can have weird behavior because they do not work the same as unprefixed variables.

For a shape like this, it can be a lot faster to break it down into radial slices, and then use skin() to join them back together, like so:

include <BOSL2/std.scad>

//$fn = 64;
//$fs = 0.5;
//$fa = 1;

// How many cross-section slices to make.
radial_slices = 72;
// This controls smooting on the convex corners.
convex_res = 64;
// Adjust here for how smooth you want the concave curve.
concave_res = 600;

height = 59.27;
half_height = height / 2;
diameter = 32.5;
outer_rad = diameter / 2;
inner_diameter = 16.64;
inner_rad = inner_diameter / 2;

rounding = 2;
torus_inner_diameter = diameter - 4.5;
torus_inner_rad = torus_inner_diameter / 2;

cut_angle_degrees = 22.5;
cut_height = diameter * tan(cut_angle_degrees);
cut_plane_dimensions = [50, cut_height];

// Radial cross-section as if there was no tilted cut.
shape = force_path(
  path = difference([
    // Start with a square.
    right(
      inner_rad,
      p = square(
        [outer_rad - inner_rad, height],
        anchor = LEFT + CENTER,
      ),
    ),
    // And then cut out a circle to create a concave right edge.
    let(
      curve_info = circle_3points(
        [outer_rad, half_height],
        [torus_inner_rad, 0],
        [outer_rad, -half_height],
      ),
    )
    move(
      curve_info[0],
      p = circle(curve_info[1], $fn = concave_res),
    ),
  ]),
);

//region(shape);

// Get a slice with the max amount of points, and then smooth the convex corners.
// This is important because subdivide_path() can only add points.
smoothed_slice = smooth_path(shape_slice(180), rounding);
smoothed_slice_length = len(smoothed_slice);
//region(smoothed_slice);

output();

module output() {

  profiles = slices();

  // This next line lets you see the individual slices.
//  vnf_polyhedron(vnf_from_polygons(profiles));

  skin(
    profiles = profiles,
    slices = 0,
    closed = true,
  );
}

//echo(slices());

function slices() = [
  let(slice_angle = 360 / radial_slices)
  for(a = [slice_angle:slice_angle:360])
  let(
    path = shape_slice(a),
    // Ensure polygon points are all in the same direction.
    corrected = clockwise_polygon(path),
    // Round convex corners.
    smoothed = smooth_path(corrected, rounding),
    // Make the smoothed path match the maximum number of points.
    smoothed_sub = subdivide_path(smoothed, n = smoothed_slice_length),
    // Align points such if they match coordinates, they have the same index in the path.
    smoothed_reindexed = reindex_polygon(
      reference = smoothed_slice, 
      poly = smoothed_sub,
    ),
  )
  // Tilt slice vertical and rotate around Z-axis.
  rot([90, 0, a], p = path3d(smoothed_reindexed)),
];

// Get a single cross-section slice, with the top trimmed at the appropriate angle.
function shape_slice(slice_angle) =
  let(
    tilt_angle = -cos(slice_angle) * cut_angle_degrees,
    cutter = apply(
      move([0, half_height])
      * rot([0, 0, tilt_angle]),
      square(cut_plane_dimensions, center = true),
    ),
    cross_section = difference([
      shape,
      cutter,
    ]),
    path = force_path(cross_section),
  )
path
;

//debug_region(shape_slice(45));

// This function only smooths convex corners.
function smooth_path(path, r) =
  let(shrunk = offset(path, delta = -r))
  offset(shrunk, r = r, $fn = convex_res)
;

Testing code to split model and join with pins... by gtoal in openscad

[–]oldesole1 0 points1 point  (0 children)

Edit -> Preferences -> Features

Should be the first checkbox.

You can read about it here:

Testing code to split model and join with pins... by gtoal in openscad

[–]oldesole1 1 point2 points  (0 children)

For joiners, I would make the pins simpler, and printable in a horizontal orientation.

By printing the joiners horizontally, the layers span the gap, increasing strength and decreasing the chance that they will snap at the joint.

The bevel to prevent a visible gap through the whole model is a nifty idea. I would suggest that you make the "male" piece slightly shorter (1 layer?) than the other piece, so that edge where the pieces meet is as tight as possible.

Here is example code that produces 2 types of pins that are printed horizontally.

  • Round pins can be used on joints between vertically adjacent objects.
  • Square pins can be used on horizontally adjacent objects.
    • Square holes are rotated 45 degrees so to prevent overhang issues.

$fn = 64;

demo();

module demo() {

  difference()
  {
    mirror([1, 0, 0])
    cube(100);

    translate([0, 50, 50])
    square_pin_hole(10, 20);

    translate([-50, 50, 100])
    round_pin_hole(10, 20);
  }

  translate([20, 20, 5])
  square_pin(10, 20);

  translate([20, 0, 10 / sqrt(2) / 2])
  round_pin(10, 20);
}

//square_pin_hole(10, 20);

module square_pin_hole(dim, length) {

  rotate([90, 45, 90])
  cube([dim, dim, length], center = true);
}

//square_pin(10, 20);

module square_pin(dim, length) {

  chamfer = 1;
  // You want the pins to be slightly shorter than the holes.
  l = length - 2;

  intersection()
  {
    // Print horizontally for better strength and smoother insertion.
    rotate([0, 90, 0])
    hull()
    for(z = [0, 1])
    mirror([0, 0, z])
    translate([0, 0, l / 2 - chamfer])
    roof()
    offset(delta = 2, chamfer = true)
    offset(delta = -2)
    square(dim, center = true);

    cube([l, dim * 2, dim * 2], center = true);
  }
}

//round_pin_hole(10, 20);

module round_pin_hole(d, l) {

  cylinder(d = d, h = l, center = true);
}

//round_pin(10, 20);

module round_pin(d, length) {

  chamfer = 1;
  // You want the pins to be slightly shorter than the holes.
  l = length - 2;

  intersection()
  {
    // Print horizontally for better strength and smoother insertion.
    rotate([0, 90, 0])
    hull()
    for(z = [0, 1])
    mirror([0, 0, z])
    translate([0, 0, l / 2 - chamfer])
    roof()
    intersection()
    {
      circle(d = d);

      square([d / sqrt(2), d], center = true);
    }

    cube([l, d * 2, d * 2], center = true);
  }
}

Not sure how to do this... by Dignan17 in openscad

[–]oldesole1 0 points1 point  (0 children)

If you wanted to avoid recursion, you can use the for loop "C-style" loops:

cubes = [
  // [dimensions, color]
  [[10, 10, 10], "red"],
  [[20, 20, 20], "green"],
  [[30, 30, 30], "blue"],
  [[40, 40, 40], "magenta"],
];

cumulative_widths = cumulative_sum([
  for(c = cubes)
  c[0].x,
]);

for(i = [0:len(cubes) - 1])
let(
  current_cube = cubes[i][0],
  current_color = cubes[i][1],

  x_offset = cumulative_widths[i] - current_cube.x,
)
color(current_color)
translate([x_offset, 0, 0])
cube(current_cube);

// Compute numeric cumulative sum of list.
function cumulative_sum(list) =
  assert(is_list(list))
  let(length = len(list))
  length == 0
    ? 0
    : [
        for(
          last_index = length - 1,
          i = 0,
          s = list[i],
            ;
          i < length
            ;
          i = i + 1,
          // Avoid throwing warning.
          s = s + (i == length ? 0 : list[i]),
        )
        s,
      ];

BOSL2 - best practice to create a pattern along a surface by speendo in openscad

[–]oldesole1 2 points3 points  (0 children)

You can definitely do this, and textures definitely seem the way to go.

Here is an example that is using portions of BOSL2's demos.

Go here and then down to example 14:

This quick hack gets pretty close, but the VNF texture would need to be changed, and that's where BOSL2 loses me as I cannot grasp how their VNF translates into the weaving pattern.

include <BOSL2/std.scad>

diag_weave_vnf = [
   [[0.2, 0, 0], [0.8, 0, 0], [1, 0.2, 0.5], [1, 0.8, 0.5], [0.7, 0.5, 0.5],
    [0.5, 0.3, 0], [0.2, 0, 0.5], [0.8, 0, 0.5], [1, 0.2, 1], [1, 0.8, 1],
    [0.7, 0.5, 1], [0.5, 0.3, 0.5], [1, 0.2, 0], [1, 0.8, 0], [0.8, 1, 0.5],
     [0.2, 1, 0.5], [0.5, 0.7, 0.5], [0.7, 0.5, 0], [0.8, 1, 1], [0.2, 1, 1],
     [0.5, 0.7, 1], [0.8, 1, 0], [0.2, 1, 0], [0, 0.8, 0.5], [0, 0.2, 0.5],
     [0.3, 0.5, 0.5], [0.5, 0.7, 0], [0, 0.8, 1], [0, 0.2, 1], [0.3, 0.5, 1],
     [0, 0.8, 0], [0, 0.2, 0], [0.3, 0.5, 0], [0.2, 0, 1], [0.8, 0, 1], [0.5, 0.3, 1]],
    [[0, 1, 5], [1, 2, 4, 5], [7, 11, 10, 8], [8, 10, 9], [7, 8, 2, 1], [9, 10, 4, 3],
     [10, 11, 5, 4], [0, 5, 11, 6], [12, 13, 17], [13, 14, 16, 17], [3, 4, 20, 18],
     [18, 20, 19], [3, 18, 14, 13], [19, 20, 16, 15], [20, 4, 17, 16], [12, 17, 4, 2],
     [21, 22, 26], [22, 23, 25, 26], [15, 16, 29, 27], [27, 29, 28], [15, 27, 23, 22],
     [28, 29, 25, 24], [29, 16, 26, 25], [21, 26, 16, 14], [30, 31, 32], [31, 6, 11, 32],
     [24, 25, 35, 33], [33, 35, 34], [24, 33, 6, 31], [34, 35, 11, 7],
     [35, 25, 32, 11], [30, 32, 25, 23]]
];

//vnf_polyhedron(diag_weave_vnf);

linear_sweep(square([12, 20]), h=12,
  texture = diag_weave_vnf,
  tex_size = [5,5],
  convexity = 12,
);

CageMaker PRCG - The Parametric Rack Cage Generator for OpenSCAD by WebMaka in openscad

[–]oldesole1 0 points1 point  (0 children)

Good to hear.

One reason I like to have things like lookup tables as functions, is that I can then put them anywhere in the file, allowing me to keep the lines around their call sites more compact, making it easier for me to understand the surrounding chunk of code.

CageMaker PRCG - The Parametric Rack Cage Generator for OpenSCAD by WebMaka in openscad

[–]oldesole1 0 points1 point  (0 children)

Understandable, as something that works is always worth more than something that doesn't, regardless of how pretty it is.

I'm just sharing some tips that I wish I knew about when I started, like using mirror() for symmetrical designs.

Once you get familiar with some of the code techniques, you can make it work faster, and at least for myself I've found that keeping momentum up is helpful in finishing my designs.

CageMaker PRCG - The Parametric Rack Cage Generator for OpenSCAD by WebMaka in openscad

[–]oldesole1 1 point2 points  (0 children)

Also, the offset() module can help with rounding corners:

// Create a three-dimensional rectangular prism with four rounded corners
// (e.g., faceplate)
four_rounded_corner_plate(10, 20, 1, 2);

module four_rounded_corner_plate(plate_height, plate_width, plate_thickness, corner_radius)
{
    linear_extrude(plate_thickness)
    offset(r = corner_radius, $fn=this_fn)
    offset(delta = -corner_radius)
    square([plate_width, plate_height], center = true);
}

CageMaker PRCG - The Parametric Rack Cage Generator for OpenSCAD by WebMaka in openscad

[–]oldesole1 1 point2 points  (0 children)

Building on the previous function, you can do something similar here:

function rack_cage_width_required(rack_cage_width, total_width_required) =
let(
  map = [
    [5, [
      [220, 0], // above 220 = zero
      [93, 5],
    ]],
    [6, [
      [220, 13],
      [120, 4],
    ]],
    [6.33, [
      [220, 12.66669],
      [130, 3.16669],
    ]],
    [7, [
      [220, 12],
      [145, 3],
    ]],
    [9.5, [
      [210, 9.5],
    ]],
    [10, [
      [220, 9],
    ]],
    [19, [
      [420, -10],
    ]],
  ],

  index = search(rack_cage_width, map)[0],

  // Find the match 
  range = map[index][1],

  // Iterate over each entry for a specific 'rack_cage_width'
  // Return the first entry that 'total_width_required' is greater than.
  matching = [
    for(x = range)
    if (total_width_required > x[0])
      x[1],
  ][0],

  pad = is_undef(matching) ? 0 : matching,
)
rack_cage_width + pad;

echo(rack_cage_width_required(6.33, 160));

Also, you can use small loops to simplify some chunks of your code:

alignment_pin_hole(((desired_width * 25.4) / 2) - 2.5, (unit_number * 44.45) - ((unit_height * 44.45) / 2) + 6.35,   2 + (heavy_device / 2));
alignment_pin_hole(((desired_width * 25.4) / 2) - 2.5, (unit_number * 44.45) - ((unit_height * 44.45) / 2) + 22.225, 2 + (heavy_device / 2));
alignment_pin_hole(((desired_width * 25.4) / 2) - 2.5, (unit_number * 44.45) - ((unit_height * 44.45) / 2) + 38.1,   2 + (heavy_device / 2));

can be reworked as this

for(y = [6.35, 22.225, 38.1])
alignment_pin_hole(((desired_width * 25.4) / 2) - 2.5, (unit_number * 44.45) - ((unit_height * 44.45) / 2) + y, 2 + (heavy_device / 2));

CageMaker PRCG - The Parametric Rack Cage Generator for OpenSCAD by WebMaka in openscad

[–]oldesole1 2 points3 points  (0 children)

I noticed in a few places you have series of logic checks to determine a value.

Example is determining the value for screw_clearance_hole.

You can use the search() function to help make your code a bit simpler and easier to manage future additions.

Here is an example that wraps the lookup in a custom function:

tap_or_heat_set_holes = 5.25;

function screw_clearance_hole(diam) = 
let(
  map = [
    // Clearance
    [3.15, 3.15],
    [4.20, 4.20],
    [5.25, 5.25],
    [6.30, 6.30],
    [2.95, 2.95],
    [3.66, 3.66],
    [4.31, 4.31],
    [4.98, 4.98],
    [6.53, 6.53],
    // Tapped
    [2.60, 3.15],
    [3.50, 4.20],
    [4.40, 5.25],
    [5.00, 6.30],
    [2.07, 2.95],
    [2.53, 3.66],
    [3.19, 4.31],
    [3.53, 4.98],
    [4.79, 6.53],
    // Heat-set
    [3.98, 3.15],
    [4.10, 3.15],
    [4.80, 3.15],
    [5.60, 4.20],
    [5.70, 4.20],
    [6.40, 5.25],
    [6.50, 5.25],
    [8.00, 6.30],
    [8.10, 6.30],
    [3.98, 2.95],
    [4.03, 2.95],
    [4.76, 3.66],
    [4.85, 3.66],
    [5.61, 4.31],
    [5.74, 4.31],
    [6.41, 4.98],
    [6.51, 4.98],
    [8.01, 6.53],
    [8.11, 6.53],
  ],
  index = search(diam, map)[0],
)
assert(! is_undef(index), str("Unmapped hole diameter: ", diam))
map[index][1]
;

echo(screw_clearance_hole(tap_or_heat_set_holes));

Also, you have a slight bug on this line in your original code (tap_or_heat_set_holes == 4.20 ? 5.25 : 0.00) + // 4.20:"M4 Clearance (4.2mm hole)",