Closed PaulBone closed 2 days ago
The problem is with fusing the swept part with the rest. If this is suppressed with:
with BuildPart() as p:
with Locations((0, 0, 0), (40, 0, 0), (0, 40, 0)):
Box(40, 40, 28)
fillet(edges().filter_by(Axis.Z), radius=4)
offset(amount=-1.2, openings=faces().sort_by(Axis.Z)[-1])
topw = faces().sort_by(Axis.Z)[-1].outer_wire()
with BuildSketch(Plane(topw @ 0, z_dir=topw % 0, x_dir=(1, 0, 0))):
Rectangle(3, 3, align=(Align.MIN, Align.MIN))
s = sweep(path=topw, mode=Mode.PRIVATE)
the part p
and the sweep s
both look independently correct. The problem is in the OCCT CAD kernel and has to do with parts that have coincident sides which should be okay but occasionally isn't. With some minor changes one can see this:
with BuildPart() as p:
with Locations((0, 0, 0), (40, 0, 0), (0, 40, 0)):
Box(40, 40, 28)
fillet(edges().filter_by(Axis.Z), radius=4)
offset(amount=-1.2, openings=faces().sort_by(Axis.Z)[-1])
topw = faces().sort_by(Axis.Z)[-1].outer_wire()
with BuildSketch(Plane(topw @ 0, z_dir=topw % 0, x_dir=(1, 0, 0))):
with Locations((0.00001, 0)):
Rectangle(3, 3, align=(Align.MIN, Align.MIN))
s = sweep(path=topw)
which moves the sweeping Rectangle
slightly off the base part and the fuse works fine. Unfortunately, the best I can offer is to avoid the problem - possibly like this:
with BuildPart() as p:
with Locations((0, 0, 0), (40, 0, 0), (0, 40, 0)):
Box(40, 40, 31)
fillet(edges().filter_by(Axis.Z), radius=4)
inside = offset(amount=-1.2, mode=Mode.PRIVATE)
inside = split(inside, Plane.XY.offset(12.5), keep=Keep.BOTTOM, mode=Mode.PRIVATE)
add(inside, mode=Mode.SUBTRACT)
top = p.faces().sort_by(Axis.Z)[-1]
with BuildSketch(Plane.XY.offset(top.bounding_box().max.Z)) as cutout:
add(top)
offset(amount=-3)
extrude(amount=-3, mode=Mode.SUBTRACT)
where the lip is created by creating a custom opening and extruding it into the hollow part.
I have an alternative fix from @gumyr, although I agree that the problem seems to be coincident cylindrical faces on the sweep and the base part.
with BuildPart() as p:
with Locations((0, 0, 0),
(40, 0, 0),
(0, 40, 0)):
Box(40, 40, 28)
fillet(edges().filter_by(Axis.Z),
radius=4)
offset(amount=-1.2,
openings=faces().sort_by(Axis.Z)[-1])
topw = faces().sort_by(Axis.Z)[-1].outer_wire()
with BuildSketch(topw^0) as s:
Rectangle(3, 3,
align=(Align.MAX, Align.MIN))
zz=sweep(path=topw, clean=False)
In this case, the default clean=True
option appears to be preventing the fuse somehow. Ultimately this seems to be mostly a kernel issue and not sure how much can be done at the build123d-level.
Thanks for the quick responses and suggestions. I tried some of these solutions on my more complex shape and it still failed. The full program is here https://github.com/PaulBone/gfthings/tree/debug_sweep (the debug_sweep branch). Run the Bin.py module as a stand-alone program (I press F5 in visual studio), there are comments with "XXX" that direct you to the problematic part.
It's probably still the same bug but I guess for some reason the work-arounds don't avoid it in this case.
Cool Gridfinity project. I was able to avoid the fusion of coincident faces from sweeping by changing strategies and creating the walls in a single BuildLine/BuildSketch as follows:
bin_size = 42
plate_height_a = 0.8
plate_height_b = 1.8
plate_height_c = 2.15
plate_base_height = 2.9
plate_height = plate_height_a + plate_height_b + plate_height_c
bin_clearance = 0.5 / 2
base_outer_dia = 8
height_units = 4
height = 7 * height_units + 0
depth = 2
width = 2
wall_thickness = 1.2
wall_height = height - plate_height
box_width = width * bin_size - bin_clearance * 2
box_depth = depth * bin_size - bin_clearance * 2
with BuildPart() as funky_bin:
with BuildSketch() as plan:
Rectangle(2 * bin_size, bin_size, align=Align.MIN)
Rectangle(bin_size, 2 * bin_size, align=Align.MIN)
fillet(plan.vertices(), base_outer_dia / 2)
sweep_path = plan.face().outer_wire()
with BuildSketch(sweep_path ^ 0) as profile:
with BuildLine() as l:
a, b, c = 1.9, 1.8, 0.7
Polyline(
(0, 0),
(wall_height, 0),
(wall_height - a, -a),
(wall_height - (a + b), -a),
(wall_height - (a + b + c), -a - c),
(wall_height - (2 * a + b + c) - c, -wall_thickness),
(0, -wall_thickness),
close=True,
)
make_face()
sweep(profile.sketch, sweep_path)
extrude(plan.sketch, amount=wall_thickness)
The following program gets stuck forever. I'm using build123d 0.6.1, Python 3.10 on Linux x86_64.
If I remove either the fillet, change the sweep to an extrude, or move the "rim" outwards so that its face doesn't touch the box (but its edge does) then the program works.
The more complete code for the shape I'm trying to create is below (but it's still simplified). I'm providing this so you can see why I'm creating a rim using a sweep and the top face's wire. I'm making a stacking lip on a bin whose shape is not a basic rounded rectangle.
Thank you.