BelfrySCAD / BOSL2

The Belfry OpenScad Library, v2.0. An OpenSCAD library of shapes, masks, and manipulators to make working with OpenSCAD easier. BETA
https://github.com/BelfrySCAD/BOSL2/wiki
BSD 2-Clause "Simplified" License
1.01k stars 115 forks source link

Implementation of gradual bridging for holes #1467

Open Andful opened 3 months ago

Andful commented 3 months ago

Is your feature request related to a problem? Please describe. When putting holes on bridged sections, it is common to gradually bridge around the hole. (In FDM printing)

Describe the solution you'd like Make a module that implements the negative of the hole (without the cylindrical part).

Describe alternatives you've considered

Example Code

module bridged_hole(w, r, levels=3, layer_height=0.2) {
    assert (levels>=1)
    linear_extrude(layer_height) rect([w, 2*r]);
    for ( i = [2:1:levels]) {
        linear_extrude(layer_height*i) regular_ngon(pow(2,i), ir=r, spin=180/pow(2,i));
    }
}

Additional context

The result of the implementation: bridged-hole

Complete code in the image.

#include <BOSL2/std.scad>

module bridged_hole(w, r, levels=3, layer_height=0.2) {
    assert (levels>=1)
    linear_extrude(layer_height) rect([w, 2*r]);
    for ( i = [2:1:levels]) {
        linear_extrude(layer_height*i) regular_ngon(pow(2,i), ir=r, spin=180/pow(2,i));
    }
}

difference() {
    cuboid([10, 10, 10], anchor=BOTTOM);
    bridged_hole(10, 2, 6, 0.2);
    cylinder(h=10, r=2, $fn=300);
}

A Fusion360 plugin that does the same: https://github.com/Finn2708/CounterboreBridging

A Hackaday article about the process: https://hackaday.com/2020/05/17/look-ma-no-support-for-my-floating-holes/

adrianVmariano commented 2 months ago

I found the example confusing. There's no hole being supported by the extra bridging. The normal application is a counterbore screw where you need to end the counterbore, so the hole needs to shrink.

It does seem like that idea would be a nice thing to add at some point.

Andful commented 2 months ago

I agree that the example is a bit odd. Ideally I would have included a sliced model, but did not have time for it. Would it still be useful to include that?

Indeed, the links I included are specifically for counterbore screw holes, but I personally experienced requiring this bridging procedure also for hexagonal nut pockets, or holes that happen to be in bridged section of my print. I personally would prefer keeping a module general enough for any hole. But specialized arguments may be added for the modules in screws.scad.

Let me know if any assistance is needed.

adrianVmariano commented 2 months ago

I don't know that a sliced model would help understanding the example. The thing that I don't understand is that the hole is not above a space and the only bridging I see is inside the hole. Hmm. Actually upon closer inspection I see that it's not inside the hole. It's hard to tell that.

I'm not sure about the right API for a general implementation. Do you pass it two (convex) polygons giving the shape of a larger hole underneath and smaller hole above? What would a general interface look like? You have a lot more bridges than I've seen anyone use for this. Is it necessary/useful? It means the bridging section gets thicker. Could be a user parameter, I suppose. It seems like figuring out the right API is perhaps the hardest part.

At the moment the dev focus is on bug fixes leading towards a stable 2.0 release, so we're trying to avoid being sidetracked by new features until after that release. But if you want to work on it, we can add the feature if you're able to get it to a reasonable state. Your preliminary code has z-fighting issues that you'd need to fix by adding extra amounts to the layers.

adrianVmariano commented 2 months ago

To be clear, I was thinking you pass it polygons as paths, not as geometry, so like bridged_hole(circle(r=6),circle(r=3),...)

It seems like you'd normally want the module to actually also make the (bottom) hole. Certainly if it's called "bridge_hole" it should do that. If that doesn't make sense it should be "hole_support" or something like that.

Andful commented 2 months ago

How would it work when fed an arbitrary shape? E.g. the smaller shape is a teardrop? I don't think the larger shape would matter too much, as long at the bridges span across the entire shape (but I might be wrong).

API seems indeed the hardest part...

Andful commented 2 months ago

Also the bottom bridges might not require to be rectangular. One might be able to fit more edges for better initial support.

E.G. temp

The code in the image:

#include <BOSL2/std.scad>

$fn=600;

difference() {
    cuboid([100, 100, 1]);
    down(0.2) linear_extrude(1) circle(r=3);
    down(1) linear_extrude(100) circle(r=2);
    #down(0.4) linear_extrude(1) intersection() {
        regular_ngon(3, ir=2);
        circle(r=3);
    }
}
Andful commented 2 months ago

Seems like a hard problem in its most general form

adrianVmariano commented 2 months ago

Yes, I think the top hole shape is the one that matters. The outer hole matters only in that you have to make sure the bridges extend up to and probably slightly beyond that outer hole. There is polygon intersection code that I think should make that part easy. So one approach, limiting to orthogonal bridging, would be to pick a direction, examine the top shape and find its outermost point in that direction and create the two bridges that defines. Then go up a layer and do the orthogonal direction the same way. And then you can continue as may layers as needed. (How many layers are needed? Do you stop when the gap between the bridges and the hole is smaller than a threshold, which would presumably be an extrusion width?) I can see being able to implement this recursively where you pass a current "remaining hole" polygon, a bridge direction and the inner hole. Note that as long as the shape is convex, it doesn't matter what it looks like. There is the interesting notion of trying to force bridges to be parallel to segments of the hole, though. It seems like if you wanted a hexagonal hole you should be able to create that exactly with just three bridge pairs. But also it seems possibly better to use 2 layers of orthogonal bridging and then finish off with a layer featuring 4 "exact" bridges. I suppose this case could be detected because it would arise if you only had one segment left in the "hole" section.

A user option could permit starting with more bridges at the bottom, but you run the risk that they intersect each other if the top hole is not small enough compared to the bottom hole, so that case would need to be detected.

So yeah, being fully general requires some thought. Really nothing is fully general. So what requires thought is how to design an algorithm and API that is as general as possible without creating excessive complexity, but also without giving up to much if flexibility.