Thanks both for your help! Both solutions give nice looking shapes but I was intentionally abusing the fillet feature to create that rounded effect on the rear.
I modified Ami's code to increase the fillet to 1 and it seems like it will work (haven't checked the STL though) but anything beyond that and I start to see weird artifacts (screenshot attached for a 1.3 fillet).
I like the idea of filleting *after* shelling though, that's not something I'd thought to try.
I also tried a different approach, creating a copy of the heart in the original code I posted, scaling it down, and cutting it out of the original heart. It doesn't produce uniformly thick walls as `shell` would do, but it's good enough for my application (a soap mould):
import cadquery as cq
def scale(workplane, x, y=None, z=None):
"""Scale workplane.
From mbway: https://github.com/CadQuery/cadquery/issues/638
"""
y = y if y is not None else x
z = z if z is not None else x
t = cq.Matrix([
[x, 0, 0, 0],
[0, y, 0, 0],
[0, 0, z, 0],
[0, 0, 0, 1]
])
return workplane.newObject([
o.transformGeometry(t) if isinstance(o, cq.Shape) else o
for o in workplane.objects
])
def heart(scale=1):
wire = cq.Workplane("XY") \
.lineTo(scale*2, scale*2) \
.threePointArc((scale*4, scale*1), (scale*3.5, 0)) \
.mirrorX()
return wire \
.extrude(scale*1.5) \
.edges(">Z") \
.fillet(scale*1.2)
result = heart().cut(scale(heart(), 0.9).translate([0.2, 0, 0]))
Screenshots attached of the front and rear (latter showing the effect I'm using the fillet to achieve).
For the record I'm still interested to see if a shell can be made to work for the shape and fillet specified in the original post.
Thanks again for your help so far!