mirror of
https://github.com/gumyr/build123d.git
synced 2025-12-06 02:30:55 -08:00
677 lines
25 KiB
Python
677 lines
25 KiB
Python
import pytest
|
|
import importlib
|
|
from math import sqrt
|
|
from build123d import *
|
|
|
|
pytestmark = pytest.mark.skipif(importlib.util.find_spec("pytest_benchmark") is not None)
|
|
|
|
|
|
def test_ppp_0101(benchmark):
|
|
def model():
|
|
"""
|
|
Too Tall Toby Party Pack 01-01 Bearing Bracket
|
|
"""
|
|
|
|
densa = 7800 / 1e6 # carbon steel density g/mm^3
|
|
densb = 2700 / 1e6 # aluminum alloy
|
|
densc = 1020 / 1e6 # ABS
|
|
|
|
with BuildPart() as p:
|
|
with BuildSketch() as s:
|
|
Rectangle(115, 50)
|
|
with Locations((5 / 2, 0)):
|
|
SlotOverall(90, 12, mode=Mode.SUBTRACT)
|
|
extrude(amount=15)
|
|
|
|
with BuildSketch(Plane.XZ.offset(50 / 2)) as s3:
|
|
with Locations((-115 / 2 + 26, 15)):
|
|
SlotOverall(42 + 2 * 26 + 12, 2 * 26, rotation=90)
|
|
zz = extrude(amount=-12)
|
|
split(bisect_by=Plane.XY)
|
|
edgs = p.part.edges().filter_by(Axis.Y).group_by(Axis.X)[-2]
|
|
fillet(edgs, 9)
|
|
|
|
with Locations(zz.faces().sort_by(Axis.Y)[0]):
|
|
with Locations((42 / 2 + 6, 0)):
|
|
CounterBoreHole(24 / 2, 34 / 2, 4)
|
|
mirror(about=Plane.XZ)
|
|
|
|
with BuildSketch() as s4:
|
|
RectangleRounded(115, 50, 6)
|
|
extrude(amount=80, mode=Mode.INTERSECT)
|
|
# fillet does not work right, mode intersect is safer
|
|
|
|
with BuildSketch(Plane.YZ) as s4:
|
|
with BuildLine() as bl:
|
|
l1 = Line((0, 0), (18 / 2, 0))
|
|
l2 = PolarLine(l1 @ 1, 8, 60, length_mode=LengthMode.VERTICAL)
|
|
l3 = Line(l2 @ 1, (0, 8))
|
|
mirror(about=Plane.YZ)
|
|
make_face()
|
|
extrude(amount=115 / 2, both=True, mode=Mode.SUBTRACT)
|
|
|
|
print(f"\npart mass = {p.part.volume*densa:0.2f}")
|
|
assert p.part.volume * densa == pytest.approx(797.15, 0.01)
|
|
|
|
benchmark(model)
|
|
|
|
|
|
def test_ppp_0102(benchmark):
|
|
def model():
|
|
"""
|
|
Too Tall Toby Party Pack 01-02 Post Cap
|
|
"""
|
|
|
|
densa = 7800 / 1e6 # carbon steel density g/mm^3
|
|
densb = 2700 / 1e6 # aluminum alloy
|
|
densc = 1020 / 1e6 # ABS
|
|
|
|
# TTT Party Pack 01: PPP0102, mass(abs) = 43.09g
|
|
with BuildPart() as p:
|
|
with BuildSketch(Plane.XZ) as sk1:
|
|
Rectangle(49, 48 - 8, align=(Align.CENTER, Align.MIN))
|
|
Rectangle(9, 48, align=(Align.CENTER, Align.MIN))
|
|
with Locations((9 / 2, 40)):
|
|
Ellipse(20, 8)
|
|
split(bisect_by=Plane.YZ)
|
|
revolve(axis=Axis.Z)
|
|
|
|
with BuildSketch(Plane.YZ.offset(-15)) as xc1:
|
|
with Locations((0, 40 / 2 - 17)):
|
|
Ellipse(10 / 2, 4 / 2)
|
|
with BuildLine(Plane.XZ) as l1:
|
|
CenterArc((-15, 40 / 2), 17, 90, 180)
|
|
sweep(path=l1)
|
|
|
|
fillet(
|
|
p.edges().filter_by(GeomType.CIRCLE, reverse=True).group_by(Axis.X)[0],
|
|
1,
|
|
)
|
|
|
|
with BuildLine(mode=Mode.PRIVATE) as lc1:
|
|
PolarLine(
|
|
(42 / 2, 0), 37, 94, length_mode=LengthMode.VERTICAL
|
|
) # construction line
|
|
|
|
pts = [
|
|
(0, 0),
|
|
(42 / 2, 0),
|
|
((lc1.line @ 1).X, (lc1.line @ 1).Y),
|
|
(0, (lc1.line @ 1).Y),
|
|
]
|
|
with BuildSketch(Plane.XZ) as sk2:
|
|
Polygon(*pts, align=None)
|
|
fillet(sk2.vertices().group_by(Axis.X)[1], 3)
|
|
revolve(axis=Axis.Z, mode=Mode.SUBTRACT)
|
|
|
|
# print(f"\npart mass = {p.part.volume*densa:0.2f}")
|
|
assert p.part.volume * densc == pytest.approx(43.09, 0.01)
|
|
|
|
benchmark(model)
|
|
|
|
|
|
def test_ppp_0103(benchmark):
|
|
def model():
|
|
"""
|
|
Too Tall Toby Party Pack 01-03 C Clamp Base
|
|
"""
|
|
|
|
densa = 7800 / 1e6 # carbon steel density g/mm^3
|
|
densb = 2700 / 1e6 # aluminum alloy
|
|
densc = 1020 / 1e6 # ABS
|
|
|
|
with BuildPart() as ppp0103:
|
|
with BuildSketch() as sk1:
|
|
RectangleRounded(34 * 2, 95, 18)
|
|
with Locations((0, -2)):
|
|
RectangleRounded((34 - 16) * 2, 95 - 18 - 14, 7, mode=Mode.SUBTRACT)
|
|
with Locations((-34 / 2, 0)):
|
|
Rectangle(34, 95, 0, mode=Mode.SUBTRACT)
|
|
extrude(amount=16)
|
|
with BuildSketch(Plane.XZ.offset(-95 / 2)) as cyl1:
|
|
with Locations((0, 16 / 2)):
|
|
Circle(16 / 2)
|
|
extrude(amount=18)
|
|
with BuildSketch(Plane.XZ.offset(95 / 2 - 14)) as cyl2:
|
|
with Locations((0, 16 / 2)):
|
|
Circle(16 / 2)
|
|
extrude(amount=23)
|
|
with Locations(Plane.XZ.offset(95 / 2 + 9)):
|
|
with Locations((0, 16 / 2)):
|
|
CounterSinkHole(5.5 / 2, 11.2 / 2, None, 90)
|
|
|
|
assert ppp0103.part.volume * densb == pytest.approx(96.13, 0.01)
|
|
|
|
benchmark(model)
|
|
|
|
|
|
def test_ppp_0104(benchmark):
|
|
def model():
|
|
"""
|
|
Too Tall Toby Party Pack 01-04 Angle Bracket
|
|
"""
|
|
|
|
densa = 7800 / 1e6 # carbon steel density g/mm^3
|
|
densb = 2700 / 1e6 # aluminum alloy
|
|
densc = 1020 / 1e6 # ABS
|
|
|
|
d1, d2, d3 = 38, 26, 16
|
|
h1, h2, h3, h4 = 20, 8, 7, 23
|
|
w1, w2, w3 = 80, 10, 5
|
|
f1, f2, f3 = 4, 10, 5
|
|
sloth1, sloth2 = 18, 12
|
|
slotw1, slotw2 = 17, 14
|
|
|
|
with BuildPart() as p:
|
|
with BuildSketch() as s:
|
|
Circle(d1 / 2)
|
|
extrude(amount=h1)
|
|
with BuildSketch(Plane.XY.offset(h1)) as s2:
|
|
Circle(d2 / 2)
|
|
extrude(amount=h2)
|
|
with BuildSketch(Plane.YZ) as s3:
|
|
Rectangle(d1 + 15, h3, align=(Align.CENTER, Align.MIN))
|
|
extrude(amount=w1 - d1 / 2)
|
|
# fillet workaround \/
|
|
ped = p.part.edges().group_by(Axis.Z)[2].filter_by(GeomType.CIRCLE)
|
|
fillet(ped, f1)
|
|
with BuildSketch(Plane.YZ) as s3a:
|
|
Rectangle(d1 + 15, 15, align=(Align.CENTER, Align.MIN))
|
|
Rectangle(d1, 15, mode=Mode.SUBTRACT, align=(Align.CENTER, Align.MIN))
|
|
extrude(amount=w1 - d1 / 2, mode=Mode.SUBTRACT)
|
|
# end fillet workaround /\
|
|
with BuildSketch() as s4:
|
|
Circle(d3 / 2)
|
|
extrude(amount=h1 + h2, mode=Mode.SUBTRACT)
|
|
with BuildSketch() as s5:
|
|
with Locations((w1 - d1 / 2 - w2 / 2, 0)):
|
|
Rectangle(w2, d1)
|
|
extrude(amount=-h4)
|
|
fillet(p.part.edges().group_by(Axis.X)[-1].sort_by(Axis.Z)[-1], f2)
|
|
fillet(p.part.edges().group_by(Axis.X)[-4].sort_by(Axis.Z)[-2], f3)
|
|
pln = Plane.YZ.offset(w1 - d1 / 2)
|
|
with BuildSketch(pln) as s6:
|
|
with Locations((0, -h4)):
|
|
SlotOverall(slotw1 * 2, sloth1, 90)
|
|
extrude(amount=-w3, mode=Mode.SUBTRACT)
|
|
with BuildSketch(pln) as s6b:
|
|
with Locations((0, -h4)):
|
|
SlotOverall(slotw2 * 2, sloth2, 90)
|
|
extrude(amount=-w2, mode=Mode.SUBTRACT)
|
|
|
|
# print(f"\npart mass = {p.part.volume*densa:0.2f}")
|
|
assert p.part.volume * densa == pytest.approx(310.00, 0.01)
|
|
|
|
benchmark(model)
|
|
|
|
|
|
def test_ppp_0105(benchmark):
|
|
def model():
|
|
"""
|
|
Too Tall Toby Party Pack 01-05 Paste Sleeve
|
|
"""
|
|
|
|
densa = 7800 / 1e6 # carbon steel density g/mm^3
|
|
densb = 2700 / 1e6 # aluminum alloy
|
|
densc = 1020 / 1e6 # ABS
|
|
|
|
with BuildPart() as p:
|
|
with BuildSketch() as s:
|
|
SlotOverall(45, 38)
|
|
offset(amount=3)
|
|
with BuildSketch(Plane.XY.offset(133 - 30)) as s2:
|
|
SlotOverall(60, 4)
|
|
offset(amount=3)
|
|
loft()
|
|
|
|
with BuildSketch() as s3:
|
|
SlotOverall(45, 38)
|
|
with BuildSketch(Plane.XY.offset(133 - 30)) as s4:
|
|
SlotOverall(60, 4)
|
|
loft(mode=Mode.SUBTRACT)
|
|
|
|
extrude(p.part.faces().sort_by(Axis.Z)[0], amount=30)
|
|
|
|
# print(f"\npart mass = {p.part.volume*densc:0.2f}")
|
|
assert p.part.volume * densc == pytest.approx(57.08, 0.01)
|
|
|
|
benchmark(model)
|
|
|
|
|
|
def test_ppp_0106(benchmark):
|
|
def model():
|
|
"""
|
|
Too Tall Toby Party Pack 01-06 Bearing Jig
|
|
"""
|
|
|
|
densa = 7800 / 1e6 # carbon steel density g/mm^3
|
|
densb = 2700 / 1e6 # aluminum alloy
|
|
densc = 1020 / 1e6 # ABS
|
|
|
|
r1, r2, r3, r4, r5 = 30 / 2, 13 / 2, 12 / 2, 10, 6 # radii used
|
|
x1 = 44 # lengths used
|
|
y1, y2, y3, y4, y_tot = 36, 36 - 22 / 2, 22 / 2, 42, 69 # widths used
|
|
|
|
with BuildSketch(Location((0, -r1, y3))) as sk_body:
|
|
with BuildLine() as l:
|
|
c1 = Line((r1, 0), (r1, y_tot), mode=Mode.PRIVATE) # construction line
|
|
m1 = Line((0, y_tot), (x1 / 2, y_tot))
|
|
m2 = JernArc(m1 @ 1, m1 % 1, r4, -90 - 45)
|
|
m3 = IntersectingLine(m2 @ 1, m2 % 1, c1)
|
|
m4 = Line(m3 @ 1, (r1, r1))
|
|
m5 = JernArc(m4 @ 1, m4 % 1, r1, -90)
|
|
m6 = Line(m5 @ 1, m1 @ 0)
|
|
mirror(make_face(l.line), Plane.YZ)
|
|
fillet(sk_body.vertices().group_by(Axis.Y)[1], 12)
|
|
with Locations((x1 / 2, y_tot - 10), (-x1 / 2, y_tot - 10)):
|
|
Circle(r2, mode=Mode.SUBTRACT)
|
|
# Keyway
|
|
with Locations((0, r1)):
|
|
Circle(r3, mode=Mode.SUBTRACT)
|
|
Rectangle(4, 3 + 6, align=(Align.CENTER, Align.MIN), mode=Mode.SUBTRACT)
|
|
|
|
with BuildPart() as p:
|
|
Box(200, 200, 22) # Oversized plate
|
|
# Cylinder underneath
|
|
Cylinder(r1, y2, align=(Align.CENTER, Align.CENTER, Align.MAX))
|
|
fillet(p.edges(Select.NEW), r5) # Weld together
|
|
extrude(sk_body.sketch, amount=-y1, mode=Mode.INTERSECT) # Cut to shape
|
|
# Remove slot
|
|
with Locations((0, y_tot - r1 - y4, 0)):
|
|
Box(
|
|
y_tot,
|
|
y_tot,
|
|
10,
|
|
align=(Align.CENTER, Align.MIN, Align.CENTER),
|
|
mode=Mode.SUBTRACT,
|
|
)
|
|
|
|
# print(f"\npart mass = {p.part.volume*densa:0.2f}")
|
|
assert p.part.volume * densa == pytest.approx(328.02, 0.01)
|
|
|
|
benchmark(model)
|
|
|
|
|
|
def test_ppp_0107(benchmark):
|
|
def model():
|
|
"""
|
|
Too Tall Toby Party Pack 01-07 Flanged Hub
|
|
"""
|
|
|
|
densa = 7800 / 1e6 # carbon steel density g/mm^3
|
|
densb = 2700 / 1e6 # aluminum alloy
|
|
densc = 1020 / 1e6 # ABS
|
|
|
|
with BuildPart() as p:
|
|
with BuildSketch() as s:
|
|
Circle(130 / 2)
|
|
extrude(amount=8)
|
|
with BuildSketch(Plane.XY.offset(8)) as s2:
|
|
Circle(84 / 2)
|
|
extrude(amount=25 - 8)
|
|
with BuildSketch(Plane.XY.offset(25)) as s3:
|
|
Circle(35 / 2)
|
|
extrude(amount=52 - 25)
|
|
with BuildSketch() as s4:
|
|
Circle(73 / 2)
|
|
extrude(amount=18, mode=Mode.SUBTRACT)
|
|
pln2 = p.part.faces().sort_by(Axis.Z)[5]
|
|
with BuildSketch(Plane.XY.offset(52)) as s5:
|
|
Circle(20 / 2)
|
|
extrude(amount=-52, mode=Mode.SUBTRACT)
|
|
fillet(
|
|
p.part.edges()
|
|
.filter_by(GeomType.CIRCLE)
|
|
.sort_by(Axis.Z)[2:-2]
|
|
.sort_by(SortBy.RADIUS)[1:],
|
|
3,
|
|
)
|
|
pln = Plane(pln2)
|
|
pln.origin = pln.origin + Vector(20 / 2, 0, 0)
|
|
pln = pln.rotated((0, 45, 0))
|
|
pln = pln.offset(-25 + 3 + 0.10)
|
|
with BuildSketch(pln) as s6:
|
|
Rectangle((73 - 35) / 2 * 1.414 + 5, 3)
|
|
zz = extrude(amount=15, taper=-20 / 2, mode=Mode.PRIVATE)
|
|
zz2 = split(zz, bisect_by=Plane.XY.offset(25), mode=Mode.PRIVATE)
|
|
zz3 = split(zz2, bisect_by=Plane.YZ.offset(35 / 2 - 1), mode=Mode.PRIVATE)
|
|
with PolarLocations(0, 3):
|
|
add(zz3)
|
|
with Locations(Plane.XY.offset(8)):
|
|
with PolarLocations(107.95 / 2, 6):
|
|
CounterBoreHole(6 / 2, 13 / 2, 4)
|
|
|
|
# print(f"\npart mass = {p.part.volume*densb:0.2f}")
|
|
assert p.part.volume * densb == pytest.approx(372.99, 0.01)
|
|
|
|
benchmark(model)
|
|
|
|
|
|
def test_ppp_0108(benchmark):
|
|
def model():
|
|
"""
|
|
Too Tall Toby Party Pack 01-08 Tie Plate
|
|
"""
|
|
|
|
densa = 7800 / 1e6 # carbon steel density g/mm^3
|
|
densb = 2700 / 1e6 # aluminum alloy
|
|
densc = 1020 / 1e6 # ABS
|
|
|
|
with BuildPart() as p:
|
|
with BuildSketch() as s1:
|
|
Rectangle(188 / 2 - 33, 162, align=(Align.MIN, Align.CENTER))
|
|
with Locations((188 / 2 - 33, 0)):
|
|
SlotOverall(190, 33 * 2, rotation=90)
|
|
mirror(about=Plane.YZ)
|
|
with GridLocations(188 - 2 * 33, 190 - 2 * 33, 2, 2):
|
|
Circle(29 / 2, mode=Mode.SUBTRACT)
|
|
Circle(84 / 2, mode=Mode.SUBTRACT)
|
|
extrude(amount=16)
|
|
|
|
with BuildPart() as p2:
|
|
with BuildSketch(Plane.XZ) as s2:
|
|
with BuildLine() as l1:
|
|
l1 = Polyline(
|
|
(222 / 2 + 14 - 40 - 40, 0),
|
|
(222 / 2 + 14 - 40, -35 + 16),
|
|
(222 / 2 + 14, -35 + 16),
|
|
(222 / 2 + 14, -35 + 16 + 30),
|
|
(222 / 2 + 14 - 40 - 40, -35 + 16 + 30),
|
|
close=True,
|
|
)
|
|
make_face()
|
|
with Locations((222 / 2, -35 + 16 + 14)):
|
|
Circle(11 / 2, mode=Mode.SUBTRACT)
|
|
extrude(amount=20 / 2, both=True)
|
|
with BuildSketch() as s3:
|
|
with Locations(l1 @ 0):
|
|
Rectangle(40 + 40, 8, align=(Align.MIN, Align.CENTER))
|
|
with Locations((40, 0)):
|
|
Rectangle(40, 20, align=(Align.MIN, Align.CENTER))
|
|
extrude(amount=30, both=True, mode=Mode.INTERSECT)
|
|
mirror(about=Plane.YZ)
|
|
|
|
# print(f"\npart mass = {p.part.volume*densa:0.2f}")
|
|
assert p.part.volume * densa == pytest.approx(3387.06, 0.01)
|
|
|
|
benchmark(model)
|
|
|
|
|
|
def test_ppp_0109(benchmark):
|
|
def model():
|
|
"""
|
|
Too Tall Toby Party Pack 01-09 Corner Tie
|
|
"""
|
|
|
|
densa = 7800 / 1e6 # carbon steel density g/mm^3
|
|
densb = 2700 / 1e6 # aluminum alloy
|
|
densc = 1020 / 1e6 # ABS
|
|
|
|
with BuildPart() as ppp109:
|
|
with BuildSketch() as one:
|
|
Rectangle(69, 75, align=(Align.MAX, Align.CENTER))
|
|
fillet(one.vertices().group_by(Axis.X)[0], 17)
|
|
extrude(amount=13)
|
|
centers = [
|
|
arc.arc_center
|
|
for arc in ppp109.edges()
|
|
.filter_by(GeomType.CIRCLE)
|
|
.group_by(Axis.Z)[-1]
|
|
]
|
|
with Locations(*centers):
|
|
CounterBoreHole(
|
|
radius=8 / 2, counter_bore_radius=15 / 2, counter_bore_depth=4
|
|
)
|
|
|
|
with BuildSketch(Plane.YZ) as two:
|
|
with Locations((0, 45)):
|
|
Circle(15)
|
|
with BuildLine() as bl:
|
|
c = Line((75 / 2, 0), (75 / 2, 60), mode=Mode.PRIVATE)
|
|
u = two.edge().find_tangent(75 / 2 + 90)[
|
|
0
|
|
] # where is the slope 75/2?
|
|
l1 = IntersectingLine(
|
|
two.edge().position_at(u), -two.edge().tangent_at(u), other=c
|
|
)
|
|
Line(l1 @ 0, (0, 45))
|
|
Polyline((0, 0), c @ 0, l1 @ 1)
|
|
mirror(about=Plane.YZ)
|
|
make_face()
|
|
with Locations((0, 45)):
|
|
Circle(12 / 2, mode=Mode.SUBTRACT)
|
|
extrude(amount=-13)
|
|
|
|
with BuildSketch(
|
|
Plane((0, 0, 0), x_dir=(1, 0, 0), z_dir=(1, 0, 1))
|
|
) as three:
|
|
Rectangle(45 * 2 / sqrt(2) - 37.5, 75, align=(Align.MIN, Align.CENTER))
|
|
with Locations(three.edges().sort_by(Axis.X)[-1].center()):
|
|
Circle(37.5)
|
|
Circle(33 / 2, mode=Mode.SUBTRACT)
|
|
split(bisect_by=Plane.YZ)
|
|
extrude(amount=6)
|
|
f = ppp109.faces().filter_by(Axis((0, 0, 0), (-1, 0, 1)))[0]
|
|
# extrude(f, until=Until.NEXT) # throws a warning
|
|
extrude(f, amount=10)
|
|
fillet(ppp109.edge(Select.NEW), 16)
|
|
|
|
# print(f"\npart mass = {ppp109.part.volume*densb:0.2f}")
|
|
assert ppp109.part.volume * densb == pytest.approx(307.23, 0.01)
|
|
|
|
benchmark(model)
|
|
|
|
|
|
def test_ppp_0110(benchmark):
|
|
def model():
|
|
"""
|
|
Too Tall Toby Party Pack 01-10 Light Cap
|
|
"""
|
|
|
|
densa = 7800 / 1e6 # carbon steel density g/mm^3
|
|
densb = 2700 / 1e6 # aluminum alloy
|
|
densc = 1020 / 1e6 # ABS
|
|
|
|
with BuildPart() as p:
|
|
with BuildSketch() as s:
|
|
with BuildLine() as l:
|
|
n1 = JernArc((0, 46), (1, 0), 40, -95)
|
|
n2 = Line((0, 0), (42, 0))
|
|
make_hull()
|
|
# hack to keep arc vertex off revolution axis
|
|
split(bisect_by=Plane.XZ.offset(-45.9999), keep=Keep.TOP)
|
|
|
|
revolve(s.sketch, axis=Axis.Y, revolution_arc=90)
|
|
extrude(faces().sort_by(Axis.Z)[-1], amount=50)
|
|
mirror(about=Plane(faces().sort_by(Axis.Z)[-1]))
|
|
mirror(about=Plane.YZ)
|
|
|
|
with BuildPart() as p2:
|
|
add(p.part)
|
|
offset(amount=-8)
|
|
|
|
with BuildPart() as pzzz:
|
|
add(p2.part)
|
|
split(bisect_by=Plane.XZ.offset(-46 + 16), keep=Keep.TOP)
|
|
fillet(faces().sort_by(Axis.Y)[-1].edges(), 12)
|
|
|
|
with BuildPart() as p3:
|
|
with BuildSketch(Plane.XZ) as s2:
|
|
add(p.part.faces().sort_by(Axis.Y)[0])
|
|
offset(amount=-8)
|
|
loft([pzzz.part.faces().sort_by(Axis.Y)[0], s2.sketch.face()])
|
|
|
|
with BuildPart() as ppp0110:
|
|
add(p.part)
|
|
add(pzzz.part, mode=Mode.SUBTRACT)
|
|
add(p3.part, mode=Mode.SUBTRACT)
|
|
|
|
# print(f"\npart mass = {ppp0110.part.volume*densc:0.2f}") # 211.30 g is correct
|
|
assert ppp0110.part.volume * densc == pytest.approx(211, 1.00)
|
|
|
|
benchmark(model)
|
|
|
|
|
|
def test_ttt_23_02_02(benchmark):
|
|
def model():
|
|
"""
|
|
Creation of a complex sheet metal part
|
|
|
|
name: ttt_sm_hanger.py
|
|
by: Gumyr
|
|
date: July 17, 2023
|
|
|
|
desc:
|
|
This example implements the sheet metal part described in Too Tall Toby's
|
|
sm_hanger CAD challenge.
|
|
|
|
Notably, a BuildLine/Curve object is filleted by providing all the vertices
|
|
and allowing the fillet operation filter out the end vertices. The
|
|
make_brake_formed operation is used both in Algebra and Builder mode to
|
|
create a sheet metal part from just an outline and some dimensions.
|
|
license:
|
|
|
|
Copyright 2023 Gumyr
|
|
|
|
Licensed under the Apache License, Version 2.0 (the "License");
|
|
you may not use this file except in compliance with the License.
|
|
You may obtain a copy of the License at
|
|
|
|
http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
Unless required by applicable law or agreed to in writing, software
|
|
distributed under the License is distributed on an "AS IS" BASIS,
|
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
See the License for the specific language governing permissions and
|
|
limitations under the License.
|
|
|
|
"""
|
|
densa = 7800 / 1e6 # carbon steel density g/mm^3
|
|
sheet_thickness = 4 * MM
|
|
|
|
# Create the main body from a side profile
|
|
with BuildPart() as side:
|
|
d = Vector(1, 0, 0).rotate(Axis.Y, 60)
|
|
with BuildLine(Plane.XZ) as side_line:
|
|
l1 = Line((0, 65), (170 / 2, 65))
|
|
l2 = PolarLine(
|
|
l1 @ 1, length=65, direction=d, length_mode=LengthMode.VERTICAL
|
|
)
|
|
l3 = Line(l2 @ 1, (170 / 2, 0))
|
|
fillet(side_line.vertices(), 7)
|
|
make_brake_formed(
|
|
thickness=sheet_thickness,
|
|
station_widths=[40, 40, 40, 112.52 / 2, 112.52 / 2, 112.52 / 2],
|
|
side=Side.RIGHT,
|
|
)
|
|
fe = side.edges().filter_by(Axis.Z).group_by(Axis.Z)[0].sort_by(Axis.Y)[-1]
|
|
fillet(fe, radius=7)
|
|
|
|
# Create the "wings" at the top
|
|
with BuildPart() as wing:
|
|
with BuildLine(Plane.YZ) as wing_line:
|
|
l1 = Line((0, 65), (80 / 2 + 1.526 * sheet_thickness, 65))
|
|
PolarLine(
|
|
l1 @ 1, 20.371288916, direction=Vector(0, 1, 0).rotate(Axis.X, -75)
|
|
)
|
|
fillet(wing_line.vertices(), 7)
|
|
make_brake_formed(
|
|
thickness=sheet_thickness,
|
|
station_widths=110 / 2,
|
|
side=Side.RIGHT,
|
|
)
|
|
bottom_edge = wing.edges().group_by(Axis.X)[-1].sort_by(Axis.Z)[0]
|
|
fillet(bottom_edge, radius=7)
|
|
|
|
# Create the tab at the top in Algebra mode
|
|
tab_line = Plane.XZ * Polyline(
|
|
(20, 65 - sheet_thickness), (56 / 2, 65 - sheet_thickness), (56 / 2, 88)
|
|
)
|
|
tab_line = fillet(tab_line.vertices(), 7)
|
|
tab = make_brake_formed(sheet_thickness, 8, tab_line, Side.RIGHT)
|
|
tab = fillet(
|
|
tab.edges().filter_by(Axis.X).group_by(Axis.Z)[-1].sort_by(Axis.Y)[-1], 5
|
|
)
|
|
tab -= Pos((0, 0, 80)) * Rot(0, 90, 0) * Hole(5, 100)
|
|
|
|
# Combine the parts together
|
|
with BuildPart() as sm_hanger:
|
|
add([side.part, wing.part])
|
|
mirror(about=Plane.XZ)
|
|
with BuildSketch(Plane.XY.offset(65)) as h1:
|
|
with Locations((20, 0)):
|
|
Rectangle(30, 30, align=(Align.MIN, Align.CENTER))
|
|
fillet(h1.vertices().group_by(Axis.X)[-1], 7)
|
|
SlotCenterPoint((154, 0), (154 / 2, 0), 20)
|
|
extrude(amount=-40, mode=Mode.SUBTRACT)
|
|
with BuildSketch() as h2:
|
|
SlotCenterPoint((206, 0), (206 / 2, 0), 20)
|
|
extrude(amount=40, mode=Mode.SUBTRACT)
|
|
add(tab)
|
|
mirror(about=Plane.YZ)
|
|
mirror(about=Plane.XZ)
|
|
|
|
# print(f"Mass: {sm_hanger.part.volume*7800*1e-6:0.1f} g")
|
|
assert sm_hanger.part.volume * densa == pytest.approx(1028, 10)
|
|
|
|
benchmark(model)
|
|
|
|
# def test_ttt_23_T_24(benchmark):
|
|
# excluding because it requires sympy
|
|
|
|
def test_ttt_24_SPO_06(benchmark):
|
|
def model():
|
|
densa = 7800 / 1e6 # carbon steel density g/mm^3
|
|
|
|
with BuildPart() as p:
|
|
with BuildSketch() as xy:
|
|
with BuildLine():
|
|
l1 = ThreePointArc((5 / 2, -1.25), (5.5 / 2, 0), (5 / 2, 1.25))
|
|
Polyline(l1 @ 0, (0, -1.25), (0, 1.25), l1 @ 1)
|
|
make_face()
|
|
extrude(amount=4)
|
|
|
|
with BuildSketch(Plane.YZ) as yz:
|
|
Trapezoid(2.5, 4, 90 - 6, align=(Align.CENTER, Align.MIN))
|
|
_, arc_center, arc_radius = full_round(
|
|
yz.edges().sort_by(SortBy.LENGTH)[0]
|
|
)
|
|
extrude(amount=10, mode=Mode.INTERSECT)
|
|
|
|
# To avoid OCCT problems, don't attempt to extend the top arc, remove instead
|
|
with BuildPart(mode=Mode.SUBTRACT) as internals:
|
|
y = p.edges().filter_by(Axis.X).sort_by(Axis.Z)[-1].center().Z
|
|
|
|
with BuildSketch(Plane.YZ.offset(4.25 / 2)) as yz:
|
|
Trapezoid(2.5, y, 90 - 6, align=(Align.CENTER, Align.MIN))
|
|
with Locations(arc_center):
|
|
Circle(arc_radius, mode=Mode.SUBTRACT)
|
|
extrude(amount=-(4.25 - 3.5) / 2)
|
|
|
|
with BuildSketch(Plane.YZ.offset(3.5 / 2)) as yz:
|
|
Trapezoid(2.5, 4, 90 - 6, align=(Align.CENTER, Align.MIN))
|
|
extrude(amount=-3.5 / 2)
|
|
|
|
with BuildSketch(Plane.XZ.offset(-2)) as xz:
|
|
with Locations((0, 4)):
|
|
RectangleRounded(4.25, 7.5, 0.5)
|
|
extrude(amount=4, mode=Mode.INTERSECT)
|
|
|
|
with Locations(
|
|
p.faces(Select.LAST).filter_by(GeomType.PLANE).sort_by(Axis.Z)[-1]
|
|
):
|
|
CounterBoreHole(0.625 / 2, 1.25 / 2, 0.5)
|
|
|
|
with BuildSketch(Plane.YZ) as rib:
|
|
with Locations((0, 0.25)):
|
|
Trapezoid(0.5, 1, 90 - 8, align=(Align.CENTER, Align.MIN))
|
|
full_round(rib.edges().sort_by(SortBy.LENGTH)[0])
|
|
extrude(amount=4.25 / 2)
|
|
|
|
mirror(about=Plane.YZ)
|
|
|
|
# part = scale(p.part, IN)
|
|
# print(f"\npart weight = {part.volume*7800e-6/LB:0.2f} lbs")
|
|
assert p.part.scale(IN).volume * densa / LB == pytest.approx(3.92, 0.03)
|
|
|
|
benchmark(model)
|