Merge branch 'dev' into docstring-updates

This commit is contained in:
Jonathan Wagenet 2025-03-07 18:19:37 -08:00 committed by GitHub
commit 7b55eb100a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
20 changed files with 641 additions and 1135 deletions

View file

@ -22,5 +22,4 @@ jobs:
python-version: ${{ matrix.python-version }} python-version: ${{ matrix.python-version }}
- name: benchmark - name: benchmark
run: | run: |
pip install pytest-benchmark
python -m pytest --benchmark-only python -m pytest --benchmark-only

View file

@ -23,4 +23,4 @@ jobs:
python-version: ${{ matrix.python-version }} python-version: ${{ matrix.python-version }}
- name: test - name: test
run: | run: |
python -m pytest -n auto python -m pytest -n auto --benchmark-disable

View file

@ -92,6 +92,13 @@ with BuildPart() as sm_hanger:
mirror(about=Plane.YZ) mirror(about=Plane.YZ)
mirror(about=Plane.XZ) mirror(about=Plane.XZ)
print(f"Mass: {sm_hanger.part.volume*7800*1e-6:0.1f} g") got_mass = sm_hanger.part.volume*7800*1e-6
want_mass = 1028
tolerance = 10
delta = abs(got_mass - want_mass)
print(f"Mass: {got_mass:0.1f} g")
assert delta < tolerance, f'{got_mass=}, {want_mass=}, {delta=}, {tolerance=}'
assert abs(got_mass - 1028) < 10, f'{got_mass=}, want=1028, tolerance=10'
show(sm_hanger) show(sm_hanger)

View file

@ -27,7 +27,7 @@ equations = [
(yl8 - 50) / (55 / 2 - xl8) - tan(radians(8)), # 8 degree slope (yl8 - 50) / (55 / 2 - xl8) - tan(radians(8)), # 8 degree slope
] ]
# There are two solutions but we want the 2nd one # There are two solutions but we want the 2nd one
solution = sympy.solve(equations, dict=True)[1] solution = {k: float(v) for k,v in sympy.solve(equations, dict=True)[1].items()}
# Create the critical points # Create the critical points
c30 = Vector(x30, solution[y30]) c30 = Vector(x30, solution[y30])
@ -58,5 +58,11 @@ with BuildPart() as curved_support:
with Locations((0, 125)): with Locations((0, 125)):
Hole(20 / 2) Hole(20 / 2)
print(curved_support.part.volume * 7800e-6) got_mass = curved_support.part.volume * 7800e-6
want_mass = 1294
delta = abs(got_mass - want_mass)
tolerance = 3
print(f"Mass: {got_mass:0.1f} g")
assert delta < tolerance, f'{got_mass=}, {want_mass=}, {delta=}, {tolerance=}'
show(curved_support) show(curved_support)

View file

@ -45,6 +45,13 @@ with BuildPart() as p:
mirror(about=Plane.YZ) mirror(about=Plane.YZ)
part = scale(p.part, IN) part = scale(p.part, IN)
print(f"\npart weight = {part.volume*7800e-6/LB:0.2f} lbs")
got_mass = part.volume*7800e-6/LB
want_mass = 3.923
tolerance = 0.02
delta = abs(got_mass - want_mass)
print(f"Mass: {got_mass:0.1f} lbs")
assert delta < tolerance, f'{got_mass=}, {want_mass=}, {delta=}, {tolerance=}'
show(p) show(p)

View file

@ -1,47 +1,54 @@
""" """
Too Tall Toby Party Pack 01-01 Bearing Bracket Too Tall Toby Party Pack 01-01 Bearing Bracket
""" """
from build123d import * from build123d import *
from ocp_vscode import * from ocp_vscode import *
densa = 7800 / 1e6 # carbon steel density g/mm^3 densa = 7800 / 1e6 # carbon steel density g/mm^3
densb = 2700 / 1e6 # aluminum alloy densb = 2700 / 1e6 # aluminum alloy
densc = 1020 / 1e6 # ABS densc = 1020 / 1e6 # ABS
with BuildPart() as p: with BuildPart() as p:
with BuildSketch() as s: with BuildSketch() as s:
Rectangle(115, 50) Rectangle(115, 50)
with Locations((5 / 2, 0)): with Locations((5 / 2, 0)):
SlotOverall(90, 12, mode=Mode.SUBTRACT) SlotOverall(90, 12, mode=Mode.SUBTRACT)
extrude(amount=15) extrude(amount=15)
with BuildSketch(Plane.XZ.offset(50 / 2)) as s3: with BuildSketch(Plane.XZ.offset(50 / 2)) as s3:
with Locations((-115 / 2 + 26, 15)): with Locations((-115 / 2 + 26, 15)):
SlotOverall(42 + 2 * 26 + 12, 2 * 26, rotation=90) SlotOverall(42 + 2 * 26 + 12, 2 * 26, rotation=90)
zz = extrude(amount=-12) zz = extrude(amount=-12)
split(bisect_by=Plane.XY) split(bisect_by=Plane.XY)
edgs = p.part.edges().filter_by(Axis.Y).group_by(Axis.X)[-2] edgs = p.part.edges().filter_by(Axis.Y).group_by(Axis.X)[-2]
fillet(edgs, 9) fillet(edgs, 9)
with Locations(zz.faces().sort_by(Axis.Y)[0]): with Locations(zz.faces().sort_by(Axis.Y)[0]):
with Locations((42 / 2 + 6, 0)): with Locations((42 / 2 + 6, 0)):
CounterBoreHole(24 / 2, 34 / 2, 4) CounterBoreHole(24 / 2, 34 / 2, 4)
mirror(about=Plane.XZ) mirror(about=Plane.XZ)
with BuildSketch() as s4: with BuildSketch() as s4:
RectangleRounded(115, 50, 6) RectangleRounded(115, 50, 6)
extrude(amount=80, mode=Mode.INTERSECT) extrude(amount=80, mode=Mode.INTERSECT)
# fillet does not work right, mode intersect is safer # fillet does not work right, mode intersect is safer
with BuildSketch(Plane.YZ) as s4: with BuildSketch(Plane.YZ) as s4:
with BuildLine() as bl: with BuildLine() as bl:
l1 = Line((0, 0), (18 / 2, 0)) l1 = Line((0, 0), (18 / 2, 0))
l2 = PolarLine(l1 @ 1, 8, 60, length_mode=LengthMode.VERTICAL) l2 = PolarLine(l1 @ 1, 8, 60, length_mode=LengthMode.VERTICAL)
l3 = Line(l2 @ 1, (0, 8)) l3 = Line(l2 @ 1, (0, 8))
mirror(about=Plane.YZ) mirror(about=Plane.YZ)
make_face() make_face()
extrude(amount=115/2, both=True, mode=Mode.SUBTRACT) extrude(amount=115/2, both=True, mode=Mode.SUBTRACT)
show_object(p) show_object(p)
print(f"\npart mass = {p.part.volume*densa:0.2f}")
got_mass = p.part.volume*densa
want_mass = 797.15
tolerance = 1
delta = abs(got_mass - want_mass)
print(f"Mass: {got_mass:0.2f} g")
assert delta < tolerance, f'{got_mass=}, {want_mass=}, {delta=}, {tolerance=}'

View file

@ -1,49 +1,57 @@
""" """
Too Tall Toby Party Pack 01-02 Post Cap Too Tall Toby Party Pack 01-02 Post Cap
""" """
from build123d import * from build123d import *
from ocp_vscode import * from ocp_vscode import *
densa = 7800 / 1e6 # carbon steel density g/mm^3 densa = 7800 / 1e6 # carbon steel density g/mm^3
densb = 2700 / 1e6 # aluminum alloy densb = 2700 / 1e6 # aluminum alloy
densc = 1020 / 1e6 # ABS densc = 1020 / 1e6 # ABS
# TTT Party Pack 01: PPP0102, mass(abs) = 43.09g # TTT Party Pack 01: PPP0102, mass(abs) = 43.09g
with BuildPart() as p: with BuildPart() as p:
with BuildSketch(Plane.XZ) as sk1: with BuildSketch(Plane.XZ) as sk1:
Rectangle(49, 48 - 8, align=(Align.CENTER, Align.MIN)) Rectangle(49, 48 - 8, align=(Align.CENTER, Align.MIN))
Rectangle(9, 48, align=(Align.CENTER, Align.MIN)) Rectangle(9, 48, align=(Align.CENTER, Align.MIN))
with Locations((9 / 2, 40)): with Locations((9 / 2, 40)):
Ellipse(20, 8) Ellipse(20, 8)
split(bisect_by=Plane.YZ) split(bisect_by=Plane.YZ)
revolve(axis=Axis.Z) revolve(axis=Axis.Z)
with BuildSketch(Plane.YZ.offset(-15)) as xc1: with BuildSketch(Plane.YZ.offset(-15)) as xc1:
with Locations((0, 40 / 2 - 17)): with Locations((0, 40 / 2 - 17)):
Ellipse(10 / 2, 4 / 2) Ellipse(10 / 2, 4 / 2)
with BuildLine(Plane.XZ) as l1: with BuildLine(Plane.XZ) as l1:
CenterArc((-15, 40 / 2), 17, 90, 180) CenterArc((-15, 40 / 2), 17, 90, 180)
sweep(path=l1) sweep(path=l1)
fillet(p.edges().filter_by(GeomType.CIRCLE, reverse=True).group_by(Axis.X)[0], 1) fillet(p.edges().filter_by(GeomType.CIRCLE, reverse=True).group_by(Axis.X)[0], 1)
with BuildLine(mode=Mode.PRIVATE) as lc1: with BuildLine(mode=Mode.PRIVATE) as lc1:
PolarLine( PolarLine(
(42 / 2, 0), 37, 94, length_mode=LengthMode.VERTICAL (42 / 2, 0), 37, 94, length_mode=LengthMode.VERTICAL
) # construction line ) # construction line
pts = [ pts = [
(0, 0), (0, 0),
(42 / 2, 0), (42 / 2, 0),
((lc1.line @ 1).X, (lc1.line @ 1).Y), ((lc1.line @ 1).X, (lc1.line @ 1).Y),
(0, (lc1.line @ 1).Y), (0, (lc1.line @ 1).Y),
] ]
with BuildSketch(Plane.XZ) as sk2: with BuildSketch(Plane.XZ) as sk2:
Polygon(*pts, align=None) Polygon(*pts, align=None)
fillet(sk2.vertices().group_by(Axis.X)[1], 3) fillet(sk2.vertices().group_by(Axis.X)[1], 3)
revolve(axis=Axis.Z, mode=Mode.SUBTRACT) revolve(axis=Axis.Z, mode=Mode.SUBTRACT)
show(p) show(p)
print(f"\npart mass = {p.part.volume*densa:0.2f}")
got_mass = p.part.volume*densc
want_mass = 43.09
tolerance = 1
delta = abs(got_mass - want_mass)
print(f"Mass: {got_mass:0.2f} g")
assert delta < tolerance, f'{got_mass=}, {want_mass=}, {delta=}, {tolerance=}'

View file

@ -1,34 +1,40 @@
""" """
Too Tall Toby Party Pack 01-03 C Clamp Base Too Tall Toby Party Pack 01-03 C Clamp Base
""" """
from build123d import * from build123d import *
from ocp_vscode import * from ocp_vscode import *
densa = 7800 / 1e6 # carbon steel density g/mm^3 densa = 7800 / 1e6 # carbon steel density g/mm^3
densb = 2700 / 1e6 # aluminum alloy densb = 2700 / 1e6 # aluminum alloy
densc = 1020 / 1e6 # ABS densc = 1020 / 1e6 # ABS
with BuildPart() as ppp0103: with BuildPart() as ppp0103:
with BuildSketch() as sk1: with BuildSketch() as sk1:
RectangleRounded(34 * 2, 95, 18) RectangleRounded(34 * 2, 95, 18)
with Locations((0, -2)): with Locations((0, -2)):
RectangleRounded((34 - 16) * 2, 95 - 18 - 14, 7, mode=Mode.SUBTRACT) RectangleRounded((34 - 16) * 2, 95 - 18 - 14, 7, mode=Mode.SUBTRACT)
with Locations((-34 / 2, 0)): with Locations((-34 / 2, 0)):
Rectangle(34, 95, 0, mode=Mode.SUBTRACT) Rectangle(34, 95, 0, mode=Mode.SUBTRACT)
extrude(amount=16) extrude(amount=16)
with BuildSketch(Plane.XZ.offset(-95 / 2)) as cyl1: with BuildSketch(Plane.XZ.offset(-95 / 2)) as cyl1:
with Locations((0, 16 / 2)): with Locations((0, 16 / 2)):
Circle(16 / 2) Circle(16 / 2)
extrude(amount=18) extrude(amount=18)
with BuildSketch(Plane.XZ.offset(95 / 2 - 14)) as cyl2: with BuildSketch(Plane.XZ.offset(95 / 2 - 14)) as cyl2:
with Locations((0, 16 / 2)): with Locations((0, 16 / 2)):
Circle(16 / 2) Circle(16 / 2)
extrude(amount=23) extrude(amount=23)
with Locations(Plane.XZ.offset(95 / 2 + 9)): with Locations(Plane.XZ.offset(95 / 2 + 9)):
with Locations((0, 16 / 2)): with Locations((0, 16 / 2)):
CounterSinkHole(5.5 / 2, 11.2 / 2, None, 90) CounterSinkHole(5.5 / 2, 11.2 / 2, None, 90)
show(ppp0103) show(ppp0103)
print(f"\npart mass = {ppp0103.part.volume*densb:0.2f}")
got_mass = ppp0103.part.volume*densb
want_mass = 96.13
tolerance = 1
delta = abs(got_mass - want_mass)
print(f"Mass: {got_mass:0.2f} g")
assert delta < tolerance, f'{got_mass=}, {want_mass=}, {delta=}, {tolerance=}'

View file

@ -1,57 +1,64 @@
""" """
Too Tall Toby Party Pack 01-04 Angle Bracket Too Tall Toby Party Pack 01-04 Angle Bracket
""" """
from build123d import * from build123d import *
from ocp_vscode import * from ocp_vscode import *
densa = 7800 / 1e6 # carbon steel density g/mm^3 densa = 7800 / 1e6 # carbon steel density g/mm^3
densb = 2700 / 1e6 # aluminum alloy densb = 2700 / 1e6 # aluminum alloy
densc = 1020 / 1e6 # ABS densc = 1020 / 1e6 # ABS
d1, d2, d3 = 38, 26, 16 d1, d2, d3 = 38, 26, 16
h1, h2, h3, h4 = 20, 8, 7, 23 h1, h2, h3, h4 = 20, 8, 7, 23
w1, w2, w3 = 80, 10, 5 w1, w2, w3 = 80, 10, 5
f1, f2, f3 = 4, 10, 5 f1, f2, f3 = 4, 10, 5
sloth1, sloth2 = 18, 12 sloth1, sloth2 = 18, 12
slotw1, slotw2 = 17, 14 slotw1, slotw2 = 17, 14
with BuildPart() as p: with BuildPart() as p:
with BuildSketch() as s: with BuildSketch() as s:
Circle(d1 / 2) Circle(d1 / 2)
extrude(amount=h1) extrude(amount=h1)
with BuildSketch(Plane.XY.offset(h1)) as s2: with BuildSketch(Plane.XY.offset(h1)) as s2:
Circle(d2 / 2) Circle(d2 / 2)
extrude(amount=h2) extrude(amount=h2)
with BuildSketch(Plane.YZ) as s3: with BuildSketch(Plane.YZ) as s3:
Rectangle(d1 + 15, h3, align=(Align.CENTER, Align.MIN)) Rectangle(d1 + 15, h3, align=(Align.CENTER, Align.MIN))
extrude(amount=w1 - d1 / 2) extrude(amount=w1 - d1 / 2)
# fillet workaround \/ # fillet workaround \/
ped = p.part.edges().group_by(Axis.Z)[2].filter_by(GeomType.CIRCLE) ped = p.part.edges().group_by(Axis.Z)[2].filter_by(GeomType.CIRCLE)
fillet(ped, f1) fillet(ped, f1)
with BuildSketch(Plane.YZ) as s3a: with BuildSketch(Plane.YZ) as s3a:
Rectangle(d1 + 15, 15, align=(Align.CENTER, Align.MIN)) Rectangle(d1 + 15, 15, align=(Align.CENTER, Align.MIN))
Rectangle(d1, 15, mode=Mode.SUBTRACT, align=(Align.CENTER, Align.MIN)) Rectangle(d1, 15, mode=Mode.SUBTRACT, align=(Align.CENTER, Align.MIN))
extrude(amount=w1 - d1 / 2, mode=Mode.SUBTRACT) extrude(amount=w1 - d1 / 2, mode=Mode.SUBTRACT)
# end fillet workaround /\ # end fillet workaround /\
with BuildSketch() as s4: with BuildSketch() as s4:
Circle(d3 / 2) Circle(d3 / 2)
extrude(amount=h1 + h2, mode=Mode.SUBTRACT) extrude(amount=h1 + h2, mode=Mode.SUBTRACT)
with BuildSketch() as s5: with BuildSketch() as s5:
with Locations((w1 - d1 / 2 - w2 / 2, 0)): with Locations((w1 - d1 / 2 - w2 / 2, 0)):
Rectangle(w2, d1) Rectangle(w2, d1)
extrude(amount=-h4) 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)[-1].sort_by(Axis.Z)[-1], f2)
fillet(p.part.edges().group_by(Axis.X)[-4].sort_by(Axis.Z)[-2], f3) fillet(p.part.edges().group_by(Axis.X)[-4].sort_by(Axis.Z)[-2], f3)
pln = Plane.YZ.offset(w1 - d1 / 2) pln = Plane.YZ.offset(w1 - d1 / 2)
with BuildSketch(pln) as s6: with BuildSketch(pln) as s6:
with Locations((0, -h4)): with Locations((0, -h4)):
SlotOverall(slotw1 * 2, sloth1, 90) SlotOverall(slotw1 * 2, sloth1, 90)
extrude(amount=-w3, mode=Mode.SUBTRACT) extrude(amount=-w3, mode=Mode.SUBTRACT)
with BuildSketch(pln) as s6b: with BuildSketch(pln) as s6b:
with Locations((0, -h4)): with Locations((0, -h4)):
SlotOverall(slotw2 * 2, sloth2, 90) SlotOverall(slotw2 * 2, sloth2, 90)
extrude(amount=-w2, mode=Mode.SUBTRACT) extrude(amount=-w2, mode=Mode.SUBTRACT)
show(p) show(p)
print(f"\npart mass = {p.part.volume*densa:0.2f}")
got_mass = p.part.volume*densa
want_mass = 310
tolerance = 1
delta = abs(got_mass - want_mass)
print(f"Mass: {got_mass:0.2f} g")
assert delta < tolerance, f'{got_mass=}, {want_mass=}, {delta=}, {tolerance=}'

View file

@ -1,30 +1,38 @@
""" """
Too Tall Toby Party Pack 01-05 Paste Sleeve Too Tall Toby Party Pack 01-05 Paste Sleeve
""" """
from build123d import * from build123d import *
from ocp_vscode import * from ocp_vscode import *
densa = 7800 / 1e6 # carbon steel density g/mm^3 densa = 7800 / 1e6 # carbon steel density g/mm^3
densb = 2700 / 1e6 # aluminum alloy densb = 2700 / 1e6 # aluminum alloy
densc = 1020 / 1e6 # ABS densc = 1020 / 1e6 # ABS
with BuildPart() as p: with BuildPart() as p:
with BuildSketch() as s: with BuildSketch() as s:
SlotOverall(45, 38) SlotOverall(45, 38)
offset(amount=3) offset(amount=3)
with BuildSketch(Plane.XY.offset(133 - 30)) as s2: with BuildSketch(Plane.XY.offset(133 - 30)) as s2:
SlotOverall(60, 4) SlotOverall(60, 4)
offset(amount=3) offset(amount=3)
loft() loft()
with BuildSketch() as s3: with BuildSketch() as s3:
SlotOverall(45, 38) SlotOverall(45, 38)
with BuildSketch(Plane.XY.offset(133 - 30)) as s4: with BuildSketch(Plane.XY.offset(133 - 30)) as s4:
SlotOverall(60, 4) SlotOverall(60, 4)
loft(mode=Mode.SUBTRACT) loft(mode=Mode.SUBTRACT)
extrude(p.part.faces().sort_by(Axis.Z)[0], amount=30) extrude(p.part.faces().sort_by(Axis.Z)[0], amount=30)
show(p) show(p)
print(f"\npart mass = {p.part.volume*densc:0.2f}")
got_mass = p.part.volume*densc
want_mass = 57.08
tolerance = 1
delta = abs(got_mass - want_mass)
print(f"Mass: {got_mass:0.2f} g")
assert delta < tolerance, f'{got_mass=}, {want_mass=}, {delta=}, {tolerance=}'

View file

@ -1,52 +1,58 @@
""" """
Too Tall Toby Party Pack 01-06 Bearing Jig Too Tall Toby Party Pack 01-06 Bearing Jig
""" """
from build123d import * from build123d import *
from ocp_vscode import * from ocp_vscode import *
densa = 7800 / 1e6 # carbon steel density g/mm^3 densa = 7800 / 1e6 # carbon steel density g/mm^3
densb = 2700 / 1e6 # aluminum alloy densb = 2700 / 1e6 # aluminum alloy
densc = 1020 / 1e6 # ABS densc = 1020 / 1e6 # ABS
r1, r2, r3, r4, r5 = 30 / 2, 13 / 2, 12 / 2, 10, 6 # radii used r1, r2, r3, r4, r5 = 30 / 2, 13 / 2, 12 / 2, 10, 6 # radii used
x1 = 44 # lengths used x1 = 44 # lengths used
y1, y2, y3, y4, y_tot = 36, 36 - 22 / 2, 22 / 2, 42, 69 # widths 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 BuildSketch(Location((0, -r1, y3))) as sk_body:
with BuildLine() as l: with BuildLine() as l:
c1 = Line((r1, 0), (r1, y_tot), mode=Mode.PRIVATE) # construction line c1 = Line((r1, 0), (r1, y_tot), mode=Mode.PRIVATE) # construction line
m1 = Line((0, y_tot), (x1 / 2, y_tot)) m1 = Line((0, y_tot), (x1 / 2, y_tot))
m2 = JernArc(m1 @ 1, m1 % 1, r4, -90 - 45) m2 = JernArc(m1 @ 1, m1 % 1, r4, -90 - 45)
m3 = IntersectingLine(m2 @ 1, m2 % 1, c1) m3 = IntersectingLine(m2 @ 1, m2 % 1, c1)
m4 = Line(m3 @ 1, (r1, r1)) m4 = Line(m3 @ 1, (r1, r1))
m5 = JernArc(m4 @ 1, m4 % 1, r1, -90) m5 = JernArc(m4 @ 1, m4 % 1, r1, -90)
m6 = Line(m5 @ 1, m1 @ 0) m6 = Line(m5 @ 1, m1 @ 0)
mirror(make_face(l.line), Plane.YZ) mirror(make_face(l.line), Plane.YZ)
fillet(sk_body.vertices().group_by(Axis.Y)[1], 12) fillet(sk_body.vertices().group_by(Axis.Y)[1], 12)
with Locations((x1 / 2, y_tot - 10), (-x1 / 2, y_tot - 10)): with Locations((x1 / 2, y_tot - 10), (-x1 / 2, y_tot - 10)):
Circle(r2, mode=Mode.SUBTRACT) Circle(r2, mode=Mode.SUBTRACT)
# Keyway # Keyway
with Locations((0, r1)): with Locations((0, r1)):
Circle(r3, mode=Mode.SUBTRACT) Circle(r3, mode=Mode.SUBTRACT)
Rectangle(4, 3 + 6, align=(Align.CENTER, Align.MIN), mode=Mode.SUBTRACT) Rectangle(4, 3 + 6, align=(Align.CENTER, Align.MIN), mode=Mode.SUBTRACT)
with BuildPart() as p: with BuildPart() as p:
Box(200, 200, 22) # Oversized plate Box(200, 200, 22) # Oversized plate
# Cylinder underneath # Cylinder underneath
Cylinder(r1, y2, align=(Align.CENTER, Align.CENTER, Align.MAX)) Cylinder(r1, y2, align=(Align.CENTER, Align.CENTER, Align.MAX))
fillet(p.edges(Select.NEW), r5) # Weld together fillet(p.edges(Select.NEW), r5) # Weld together
extrude(sk_body.sketch, amount=-y1, mode=Mode.INTERSECT) # Cut to shape extrude(sk_body.sketch, amount=-y1, mode=Mode.INTERSECT) # Cut to shape
# Remove slot # Remove slot
with Locations((0, y_tot - r1 - y4, 0)): with Locations((0, y_tot - r1 - y4, 0)):
Box( Box(
y_tot, y_tot,
y_tot, y_tot,
10, 10,
align=(Align.CENTER, Align.MIN, Align.CENTER), align=(Align.CENTER, Align.MIN, Align.CENTER),
mode=Mode.SUBTRACT, mode=Mode.SUBTRACT,
) )
show(p) show(p)
print(f"\npart mass = {p.part.volume*densa:0.2f}")
print(p.part.bounding_box().size)
got_mass = p.part.volume*densa
want_mass = 328.02
tolerance = 1
delta = abs(got_mass - want_mass)
print(f"Mass: {got_mass:0.2f} g")
assert delta < tolerance, f'{got_mass=}, {want_mass=}, {delta=}, {tolerance=}'

View file

@ -1,52 +1,59 @@
""" """
Too Tall Toby Party Pack 01-07 Flanged Hub Too Tall Toby Party Pack 01-07 Flanged Hub
""" """
from build123d import * from build123d import *
from ocp_vscode import * from ocp_vscode import *
densa = 7800 / 1e6 # carbon steel density g/mm^3 densa = 7800 / 1e6 # carbon steel density g/mm^3
densb = 2700 / 1e6 # aluminum alloy densb = 2700 / 1e6 # aluminum alloy
densc = 1020 / 1e6 # ABS densc = 1020 / 1e6 # ABS
with BuildPart() as p: with BuildPart() as p:
with BuildSketch() as s: with BuildSketch() as s:
Circle(130 / 2) Circle(130 / 2)
extrude(amount=8) extrude(amount=8)
with BuildSketch(Plane.XY.offset(8)) as s2: with BuildSketch(Plane.XY.offset(8)) as s2:
Circle(84 / 2) Circle(84 / 2)
extrude(amount=25 - 8) extrude(amount=25 - 8)
with BuildSketch(Plane.XY.offset(25)) as s3: with BuildSketch(Plane.XY.offset(25)) as s3:
Circle(35 / 2) Circle(35 / 2)
extrude(amount=52 - 25) extrude(amount=52 - 25)
with BuildSketch() as s4: with BuildSketch() as s4:
Circle(73 / 2) Circle(73 / 2)
extrude(amount=18, mode=Mode.SUBTRACT) extrude(amount=18, mode=Mode.SUBTRACT)
pln2 = p.part.faces().sort_by(Axis.Z)[5] pln2 = p.part.faces().sort_by(Axis.Z)[5]
with BuildSketch(Plane.XY.offset(52)) as s5: with BuildSketch(Plane.XY.offset(52)) as s5:
Circle(20 / 2) Circle(20 / 2)
extrude(amount=-52, mode=Mode.SUBTRACT) extrude(amount=-52, mode=Mode.SUBTRACT)
fillet( fillet(
p.part.edges() p.part.edges()
.filter_by(GeomType.CIRCLE) .filter_by(GeomType.CIRCLE)
.sort_by(Axis.Z)[2:-2] .sort_by(Axis.Z)[2:-2]
.sort_by(SortBy.RADIUS)[1:], .sort_by(SortBy.RADIUS)[1:],
3, 3,
) )
pln = Plane(pln2) pln = Plane(pln2)
pln.origin = pln.origin + Vector(20 / 2, 0, 0) pln.origin = pln.origin + Vector(20 / 2, 0, 0)
pln = pln.rotated((0, 45, 0)) pln = pln.rotated((0, 45, 0))
pln = pln.offset(-25 + 3 + 0.10) pln = pln.offset(-25 + 3 + 0.10)
with BuildSketch(pln) as s6: with BuildSketch(pln) as s6:
Rectangle((73 - 35) / 2 * 1.414 + 5, 3) Rectangle((73 - 35) / 2 * 1.414 + 5, 3)
zz = extrude(amount=15, taper=-20 / 2, mode=Mode.PRIVATE) zz = extrude(amount=15, taper=-20 / 2, mode=Mode.PRIVATE)
zz2 = split(zz, bisect_by=Plane.XY.offset(25), 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) zz3 = split(zz2, bisect_by=Plane.YZ.offset(35 / 2 - 1), mode=Mode.PRIVATE)
with PolarLocations(0, 3): with PolarLocations(0, 3):
add(zz3) add(zz3)
with Locations(Plane.XY.offset(8)): with Locations(Plane.XY.offset(8)):
with PolarLocations(107.95 / 2, 6): with PolarLocations(107.95 / 2, 6):
CounterBoreHole(6 / 2, 13 / 2, 4) CounterBoreHole(6 / 2, 13 / 2, 4)
show(p) show(p)
print(f"\npart mass = {p.part.volume*densb:0.2f}")
got_mass = p.part.volume*densb
want_mass = 372.99
tolerance = 1
delta = abs(got_mass - want_mass)
print(f"Mass: {got_mass:0.2f} g")
assert delta < tolerance, f'{got_mass=}, {want_mass=}, {delta=}, {tolerance=}'

View file

@ -1,47 +1,54 @@
""" """
Too Tall Toby Party Pack 01-08 Tie Plate Too Tall Toby Party Pack 01-08 Tie Plate
""" """
from build123d import * from build123d import *
from ocp_vscode import * from ocp_vscode import *
densa = 7800 / 1e6 # carbon steel density g/mm^3 densa = 7800 / 1e6 # carbon steel density g/mm^3
densb = 2700 / 1e6 # aluminum alloy densb = 2700 / 1e6 # aluminum alloy
densc = 1020 / 1e6 # ABS densc = 1020 / 1e6 # ABS
with BuildPart() as p: with BuildPart() as p:
with BuildSketch() as s1: with BuildSketch() as s1:
Rectangle(188 / 2 - 33, 162, align=(Align.MIN, Align.CENTER)) Rectangle(188 / 2 - 33, 162, align=(Align.MIN, Align.CENTER))
with Locations((188 / 2 - 33, 0)): with Locations((188 / 2 - 33, 0)):
SlotOverall(190, 33 * 2, rotation=90) SlotOverall(190, 33 * 2, rotation=90)
mirror(about=Plane.YZ) mirror(about=Plane.YZ)
with GridLocations(188 - 2 * 33, 190 - 2 * 33, 2, 2): with GridLocations(188 - 2 * 33, 190 - 2 * 33, 2, 2):
Circle(29 / 2, mode=Mode.SUBTRACT) Circle(29 / 2, mode=Mode.SUBTRACT)
Circle(84 / 2, mode=Mode.SUBTRACT) Circle(84 / 2, mode=Mode.SUBTRACT)
extrude(amount=16) extrude(amount=16)
with BuildPart() as p2: with BuildPart() as p2:
with BuildSketch(Plane.XZ) as s2: with BuildSketch(Plane.XZ) as s2:
with BuildLine() as l1: with BuildLine() as l1:
l1 = Polyline( l1 = Polyline(
(222 / 2 + 14 - 40 - 40, 0), (222 / 2 + 14 - 40 - 40, 0),
(222 / 2 + 14 - 40, -35 + 16), (222 / 2 + 14 - 40, -35 + 16),
(222 / 2 + 14, -35 + 16), (222 / 2 + 14, -35 + 16),
(222 / 2 + 14, -35 + 16 + 30), (222 / 2 + 14, -35 + 16 + 30),
(222 / 2 + 14 - 40 - 40, -35 + 16 + 30), (222 / 2 + 14 - 40 - 40, -35 + 16 + 30),
close=True, close=True,
) )
make_face() make_face()
with Locations((222 / 2, -35 + 16 + 14)): with Locations((222 / 2, -35 + 16 + 14)):
Circle(11 / 2, mode=Mode.SUBTRACT) Circle(11 / 2, mode=Mode.SUBTRACT)
extrude(amount=20 / 2, both=True) extrude(amount=20 / 2, both=True)
with BuildSketch() as s3: with BuildSketch() as s3:
with Locations(l1 @ 0): with Locations(l1 @ 0):
Rectangle(40 + 40, 8, align=(Align.MIN, Align.CENTER)) Rectangle(40 + 40, 8, align=(Align.MIN, Align.CENTER))
with Locations((40, 0)): with Locations((40, 0)):
Rectangle(40, 20, align=(Align.MIN, Align.CENTER)) Rectangle(40, 20, align=(Align.MIN, Align.CENTER))
extrude(amount=30, both=True, mode=Mode.INTERSECT) extrude(amount=30, both=True, mode=Mode.INTERSECT)
mirror(about=Plane.YZ) mirror(about=Plane.YZ)
show(p) show(p)
print(f"\npart mass = {p.part.volume*densa:0.2f}")
got_mass = p.part.volume*densa
want_mass = 3387.06
tolerance = 1
delta = abs(got_mass - want_mass)
print(f"Mass: {got_mass:0.2f} g")
assert delta < tolerance, f'{got_mass=}, {want_mass=}, {delta=}, {tolerance=}'

View file

@ -1,56 +1,62 @@
""" """
Too Tall Toby Party Pack 01-09 Corner Tie Too Tall Toby Party Pack 01-09 Corner Tie
""" """
from math import sqrt from math import sqrt
from build123d import * from build123d import *
from ocp_vscode import * from ocp_vscode import *
densa = 7800 / 1e6 # carbon steel density g/mm^3 densa = 7800 / 1e6 # carbon steel density g/mm^3
densb = 2700 / 1e6 # aluminum alloy densb = 2700 / 1e6 # aluminum alloy
densc = 1020 / 1e6 # ABS densc = 1020 / 1e6 # ABS
with BuildPart() as ppp109: with BuildPart() as ppp109:
with BuildSketch() as one: with BuildSketch() as one:
Rectangle(69, 75, align=(Align.MAX, Align.CENTER)) Rectangle(69, 75, align=(Align.MAX, Align.CENTER))
fillet(one.vertices().group_by(Axis.X)[0], 17) fillet(one.vertices().group_by(Axis.X)[0], 17)
extrude(amount=13) extrude(amount=13)
centers = [ centers = [
arc.arc_center arc.arc_center
for arc in ppp109.edges().filter_by(GeomType.CIRCLE).group_by(Axis.Z)[-1] for arc in ppp109.edges().filter_by(GeomType.CIRCLE).group_by(Axis.Z)[-1]
] ]
with Locations(*centers): with Locations(*centers):
CounterBoreHole(radius=8 / 2, counter_bore_radius=15 / 2, counter_bore_depth=4) CounterBoreHole(radius=8 / 2, counter_bore_radius=15 / 2, counter_bore_depth=4)
with BuildSketch(Plane.YZ) as two: with BuildSketch(Plane.YZ) as two:
with Locations((0, 45)): with Locations((0, 45)):
Circle(15) Circle(15)
with BuildLine() as bl: with BuildLine() as bl:
c = Line((75 / 2, 0), (75 / 2, 60), mode=Mode.PRIVATE) 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? u = two.edge().find_tangent(75 / 2 + 90)[0] # where is the slope 75/2?
l1 = IntersectingLine( l1 = IntersectingLine(
two.edge().position_at(u), -two.edge().tangent_at(u), other=c two.edge().position_at(u), -two.edge().tangent_at(u), other=c
) )
Line(l1 @ 0, (0, 45)) Line(l1 @ 0, (0, 45))
Polyline((0, 0), c @ 0, l1 @ 1) Polyline((0, 0), c @ 0, l1 @ 1)
mirror(about=Plane.YZ) mirror(about=Plane.YZ)
make_face() make_face()
with Locations((0, 45)): with Locations((0, 45)):
Circle(12 / 2, mode=Mode.SUBTRACT) Circle(12 / 2, mode=Mode.SUBTRACT)
extrude(amount=-13) extrude(amount=-13)
with BuildSketch(Plane((0, 0, 0), x_dir=(1, 0, 0), z_dir=(1, 0, 1))) as three: 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)) Rectangle(45 * 2 / sqrt(2) - 37.5, 75, align=(Align.MIN, Align.CENTER))
with Locations(three.edges().sort_by(Axis.X)[-1].center()): with Locations(three.edges().sort_by(Axis.X)[-1].center()):
Circle(37.5) Circle(37.5)
Circle(33 / 2, mode=Mode.SUBTRACT) Circle(33 / 2, mode=Mode.SUBTRACT)
split(bisect_by=Plane.YZ) split(bisect_by=Plane.YZ)
extrude(amount=6) extrude(amount=6)
f = ppp109.faces().filter_by(Axis((0, 0, 0), (-1, 0, 1)))[0] f = ppp109.faces().filter_by(Axis((0, 0, 0), (-1, 0, 1)))[0]
# extrude(f, until=Until.NEXT) # throws a warning # extrude(f, until=Until.NEXT) # throws a warning
extrude(f, amount=10) extrude(f, amount=10)
fillet(ppp109.edge(Select.NEW), 16) fillet(ppp109.edge(Select.NEW), 16)
show(ppp109) show(ppp109)
print(f"\npart mass = {ppp109.part.volume*densb:0.2f}")
got_mass = ppp109.part.volume*densb
want_mass = 307.23
tolerance = 1
delta = abs(got_mass - want_mass)
print(f"Mass: {got_mass:0.2f} g")
assert delta < tolerance, f'{got_mass=}, {want_mass=}, {delta=}, {tolerance=}'

View file

@ -1,52 +1,59 @@
""" """
Too Tall Toby Party Pack 01-10 Light Cap Too Tall Toby Party Pack 01-10 Light Cap
""" """
from build123d import * from math import sqrt, asin, pi
from ocp_vscode import * from build123d import *
from ocp_vscode import *
densa = 7800 / 1e6 # carbon steel density g/mm^3
densb = 2700 / 1e6 # aluminum alloy densa = 7800 / 1e6 # carbon steel density g/mm^3
densc = 1020 / 1e6 # ABS densb = 2700 / 1e6 # aluminum alloy
densc = 1020 / 1e6 # ABS
with BuildPart() as p:
with BuildSketch(Plane.YZ.rotated((90, 0, 0))) as s: # The smaller cross-section is defined as having R40, height 46,
with BuildLine() as l: # and base width 84, so clearly it's not entirely a half-circle or
n2 = JernArc((0, 46), (1, 0), 40, -90) # similar; the base's extreme points need to connect via tangents
n3 = Line(n2 @ 1, n2 @ 0) # to the R40 arc centered 6mm above the baseline.
make_face() #
# Compute the angle of the tangent line (working with the
with BuildLine() as l2: # left/negativeX side, given symmetry) by observing the tangent
m1 = Line((0, 0), (42, 0)) # point (T), the circle's center (O), and the baseline's edge (P)
m2 = Line((0, 0.01), (42, 0.01)) # form a right triangle, so:
m3 = Line(m1 @ 0, m2 @ 0)
m4 = Line(m1 @ 1, m2 @ 1) OT=40
make_face() OP=sqrt((-84/2)**2+(-6)**2)
make_hull() TP=sqrt(OP**2-40**2)
extrude(amount=100 / 2) OPT_degrees = asin(OT/OP) * 180/pi
revolve(s.sketch, axis=Axis.Y.reverse(), revolution_arc=-90) # Correct for the fact that OP isn't horizontal.
mirror(about=Plane(p.part.faces().sort_by(Axis.X)[-1])) OP_to_X_axis_degrees = asin(6/OP) * 180/pi
mirror(about=Plane.XY) left_tangent_degrees = OPT_degrees + OP_to_X_axis_degrees
left_tangent_length = TP
with BuildPart() as p2: with BuildPart() as outer:
add(p.part) with BuildSketch(Plane.XZ) as sk:
offset(amount=-8) with BuildLine():
l1 = PolarLine(start=(-84/2, 0), length=left_tangent_length, angle=left_tangent_degrees)
with BuildPart() as pzzz: l2 = TangentArc(l1@1, (0, 46), tangent=l1%1)
add(p2.part) l3 = offset(amount=-8, side=Side.RIGHT, closed=False, mode=Mode.ADD)
split(bisect_by=Plane.XZ.offset(46 - 16), keep=Keep.BOTTOM) l4 = Line(l1@0, l3@1)
fillet(pzzz.part.faces().filter_by(Axis.Y).sort_by(Axis.Y)[0].edges(), 12) l5 = Line(l3@0, l2@1)
l6 = Line(l3@0, (0, 46-16))
with BuildPart() as p3: l7 = IntersectingLine(start=l6@1, direction=(-1,0), other=l3)
with BuildSketch(Plane.XZ) as s2: make_face()
add(p.part.faces().sort_by(Axis.Y)[-1]) revolve(axis=Axis.Z)
offset(amount=-8) sk = sk.sketch & Plane.XZ*Rectangle(1000, 1000, align=[Align.CENTER, Align.MIN])
loft([p2.part.faces().sort_by(Axis.Y)[-5], s2.sketch.faces()[0]]) positive_Z = Box(100, 100, 100, align=[Align.CENTER, Align.MIN, Align.MIN])
p = outer.part & positive_Z
with BuildPart() as ppp0110: cross_section = sk + mirror(sk, about=Plane.YZ)
add(p.part) p += extrude(cross_section, amount=50)
add(pzzz.part, mode=Mode.SUBTRACT) p += mirror(p, about=Plane.XZ.offset(50))
add(p3.part, mode=Mode.SUBTRACT) p += fillet(p.edges().filter_by(GeomType.LINE).filter_by(Axis.Y).group_by(Axis.Z)[-1], radius=8)
ppp0110 = p
show(ppp0110)
print(f"\npart mass = {ppp0110.part.volume*densc:0.2f}") got_mass = ppp0110.volume*densc
want_mass = 211.30
tolerance = 1
delta = abs(got_mass - want_mass)
print(f"Mass: {got_mass:0.1f} g")
assert delta < tolerance, f'{got_mass=}, {want_mass=}, {delta=}, {tolerance=}'
show(ppp0110)

View file

@ -61,13 +61,15 @@ ocp_vscode = [
# development dependencies # development dependencies
development = [ development = [
"wheel", "black",
"mypy",
"pylint",
"pytest", "pytest",
"pytest-benchmark",
"pytest-cov", "pytest-cov",
"pytest-xdist", "pytest-xdist",
"pylint", "sympy",
"mypy", "wheel",
"black",
] ]
# typing stubs for the OCP CAD kernel # typing stubs for the OCP CAD kernel
@ -75,11 +77,6 @@ stubs = [
"cadquery-ocp-stubs >= 7.8, < 7.9", "cadquery-ocp-stubs >= 7.8, < 7.9",
] ]
# dependency to run the pytest benchmarks
benchmark = [
"pytest-benchmark",
]
# dependencies to build the docs # dependencies to build the docs
docs = [ docs = [
"sphinx==8.1.3", # pin for stability of docs builds "sphinx==8.1.3", # pin for stability of docs builds
@ -94,7 +91,6 @@ docs = [
all = [ all = [
"build123d[ocp_vscode]", "build123d[ocp_vscode]",
"build123d[development]", "build123d[development]",
"build123d[benchmark]",
"build123d[docs]", "build123d[docs]",
# "build123d[stubs]", # excluded for now as mypy fails # "build123d[stubs]", # excluded for now as mypy fails
] ]

View file

@ -719,6 +719,7 @@ class PolarLine(BaseEdgeObject):
start (VectorLike): start point start (VectorLike): start point
length (float): line length length (float): line length
angle (float, optional): angle from the local x-axis angle (float, optional): angle from the local x-axis
direction (VectorLike, optional): vector direction to determine angle
length_mode (LengthMode, optional): how length defines the line. length_mode (LengthMode, optional): how length defines the line.
Defaults to LengthMode.DIAGONAL Defaults to LengthMode.DIAGONAL
mode (Mode, optional): combination mode. Defaults to Mode.ADD mode (Mode, optional): combination mode. Defaults to Mode.ADD
@ -750,7 +751,7 @@ class PolarLine(BaseEdgeObject):
) )
if direction is not None: if direction is not None:
direction_localized = WorkplaneList.localize(direction) direction_localized = WorkplaneList.localize(direction).normalized()
angle = Vector(1, 0, 0).get_angle(direction_localized) angle = Vector(1, 0, 0).get_angle(direction_localized)
elif angle is not None: elif angle is not None:
direction_localized = polar_workplane.x_dir.rotate( direction_localized = polar_workplane.x_dir.rotate(

View file

@ -1,684 +1,103 @@
import pytest import pytest
from math import sqrt import sys
from build123d import * from build123d import *
from pathlib import Path
from unittest.mock import Mock
mock_module = Mock()
mock_module.show = Mock()
mock_module.show_object = Mock()
mock_module.show_all = Mock()
sys.modules["ocp_vscode"] = mock_module
_ = pytest.importorskip("pytest_benchmark")
pytest_benchmark = pytest.importorskip("pytest_benchmark") def _read_docs_ttt_code(name):
checkout_dir = Path(__file__).parent.parent
ttt_dir = checkout_dir / "docs/assets/ttt"
name = "ttt-" + name + ".py"
with open(ttt_dir / name, "r") as f:
return f.read()
def test_ppp_0101(benchmark): def test_ppp_0101(benchmark):
def model(): def model():
""" exec(_read_docs_ttt_code("ppp0101"))
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) benchmark(model)
def test_ppp_0102(benchmark): def test_ppp_0102(benchmark):
def model(): def model():
""" exec(_read_docs_ttt_code("ppp0102"))
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) benchmark(model)
def test_ppp_0103(benchmark): def test_ppp_0103(benchmark):
def model(): def model():
""" exec(_read_docs_ttt_code("ppp0103"))
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) benchmark(model)
def test_ppp_0104(benchmark): def test_ppp_0104(benchmark):
def model(): def model():
""" exec(_read_docs_ttt_code("ppp0104"))
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) benchmark(model)
def test_ppp_0105(benchmark): def test_ppp_0105(benchmark):
def model(): def model():
""" exec(_read_docs_ttt_code("ppp0105"))
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) benchmark(model)
def test_ppp_0106(benchmark): def test_ppp_0106(benchmark):
def model(): def model():
""" exec(_read_docs_ttt_code("ppp0106"))
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) benchmark(model)
def test_ppp_0107(benchmark): def test_ppp_0107(benchmark):
def model(): def model():
""" exec(_read_docs_ttt_code("ppp0107"))
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) benchmark(model)
def test_ppp_0108(benchmark): def test_ppp_0108(benchmark):
def model(): def model():
""" exec(_read_docs_ttt_code("ppp0108"))
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) benchmark(model)
def test_ppp_0109(benchmark): def test_ppp_0109(benchmark):
def model(): def model():
""" exec(_read_docs_ttt_code("ppp0109"))
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) benchmark(model)
def test_ppp_0110(benchmark): def test_ppp_0110(benchmark):
def model(): def model():
""" exec(_read_docs_ttt_code("ppp0110"))
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) benchmark(model)
def test_ttt_23_02_02(benchmark): def test_ttt_23_02_02(benchmark):
def model(): def model():
""" exec(_read_docs_ttt_code("23-02-02-sm_hanger"))
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) benchmark(model)
def test_ttt_23_T_24(benchmark):
# def test_ttt_23_T_24(benchmark): def model():
# excluding because it requires sympy exec(_read_docs_ttt_code("23-t-24-curved_support"))
benchmark(model)
def test_ttt_24_SPO_06(benchmark): def test_ttt_24_SPO_06(benchmark):
def model(): def model():
densa = 7800 / 1e6 # carbon steel density g/mm^3 exec(_read_docs_ttt_code("24-SPO-06-Buffer_Stand"))
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) benchmark(model)
@pytest.mark.parametrize("test_input", [100, 1000, 10000, 100000]) @pytest.mark.parametrize("test_input", [100, 1000, 10000, 100000])
def test_mesher_benchmark(benchmark, test_input): def test_mesher_benchmark(benchmark, test_input):
# in the 100_000 case test should take on the order of 0.2 seconds # in the 100_000 case test should take on the order of 0.2 seconds

View file

@ -247,35 +247,37 @@ class BuildLineTests(unittest.TestCase):
def test_polar_line(self): def test_polar_line(self):
"""Test 2D and 3D polar lines""" """Test 2D and 3D polar lines"""
with BuildLine() as bl: with BuildLine():
PolarLine((0, 0), sqrt(2), 45) a1 = PolarLine((0, 0), sqrt(2), 45)
self.assertTupleAlmostEquals((bl.edges()[0] @ 1).to_tuple(), (1, 1, 0), 5) d1 = PolarLine((0, 0), sqrt(2), direction=(1, 1))
self.assertTupleAlmostEquals((a1 @ 1).to_tuple(), (1, 1, 0), 5)
self.assertTupleAlmostEquals((a1 @ 1).to_tuple(), (d1 @ 1).to_tuple(), 5)
self.assertTrue(isinstance(a1, Edge))
self.assertTrue(isinstance(d1, Edge))
with BuildLine() as bl: with BuildLine():
PolarLine((0, 0), 1, 30) a2 = PolarLine((0, 0), 1, 30)
self.assertTupleAlmostEquals( d2 = PolarLine((0, 0), 1, direction=(sqrt(3), 1))
(bl.edges()[0] @ 1).to_tuple(), (sqrt(3) / 2, 0.5, 0), 5 self.assertTupleAlmostEquals((a2 @ 1).to_tuple(), (sqrt(3) / 2, 0.5, 0), 5)
) self.assertTupleAlmostEquals((a2 @ 1).to_tuple(), (d2 @ 1).to_tuple(), 5)
with BuildLine() as bl: with BuildLine():
PolarLine((0, 0), 1, 150) a3 = PolarLine((0, 0), 1, 150)
self.assertTupleAlmostEquals( d3 = PolarLine((0, 0), 1, direction=(-sqrt(3), 1))
(bl.edges()[0] @ 1).to_tuple(), (-sqrt(3) / 2, 0.5, 0), 5 self.assertTupleAlmostEquals((a3 @ 1).to_tuple(), (-sqrt(3) / 2, 0.5, 0), 5)
) self.assertTupleAlmostEquals((a3 @ 1).to_tuple(), (d3 @ 1).to_tuple(), 5)
with BuildLine() as bl: with BuildLine():
PolarLine((0, 0), 1, angle=30, length_mode=LengthMode.HORIZONTAL) a4 = PolarLine((0, 0), 1, angle=30, length_mode=LengthMode.HORIZONTAL)
self.assertTupleAlmostEquals( d4 = PolarLine((0, 0), 1, direction=(sqrt(3), 1), length_mode=LengthMode.HORIZONTAL)
(bl.edges()[0] @ 1).to_tuple(), (1, 1 / sqrt(3), 0), 5 self.assertTupleAlmostEquals((a4 @ 1).to_tuple(), (1, 1 / sqrt(3), 0), 5)
) self.assertTupleAlmostEquals((a4 @ 1).to_tuple(), (d4 @ 1).to_tuple(), 5)
with BuildLine(Plane.XZ) as bl: with BuildLine(Plane.XZ):
PolarLine((0, 0), 1, angle=30, length_mode=LengthMode.VERTICAL) a5 = PolarLine((0, 0), 1, angle=30, length_mode=LengthMode.VERTICAL)
self.assertTupleAlmostEquals((bl.edges()[0] @ 1).to_tuple(), (sqrt(3), 0, 1), 5) d5 = PolarLine((0, 0), 1, direction=(sqrt(3), 1), length_mode=LengthMode.VERTICAL)
self.assertTupleAlmostEquals((a5 @ 1).to_tuple(), (sqrt(3), 0, 1), 5)
l1 = PolarLine((0, 0), 10, direction=(1, 1)) self.assertTupleAlmostEquals((a5 @ 1).to_tuple(), (d5 @ 1).to_tuple(), 5)
self.assertTupleAlmostEquals((l1 @ 1).to_tuple(), (10, 10, 0), 5)
self.assertTrue(isinstance(l1, Edge))
with self.assertRaises(ValueError): with self.assertRaises(ValueError):
PolarLine((0, 0), 1) PolarLine((0, 0), 1)

View file

@ -18,6 +18,7 @@ import unittest
_examples_dir = Path(os.path.abspath(os.path.dirname(__file__))).parent / "examples" _examples_dir = Path(os.path.abspath(os.path.dirname(__file__))).parent / "examples"
_ttt_dir = Path(os.path.abspath(os.path.dirname(__file__))).parent / "docs/assets/ttt"
_MOCK_OCP_VSCODE_CONTENTS = """ _MOCK_OCP_VSCODE_CONTENTS = """
from pathlib import Path from pathlib import Path
@ -72,8 +73,7 @@ def generate_example_test(path: Path):
class TestExamples(unittest.TestCase): class TestExamples(unittest.TestCase):
"""Tests build123d examples.""" """Tests build123d examples."""
for example in sorted(list(_examples_dir.iterdir()) + list(_ttt_dir.iterdir())):
for example in sorted(_examples_dir.iterdir()):
if example.name.startswith("_") or not example.name.endswith(".py"): if example.name.startswith("_") or not example.name.endswith(".py"):
continue continue
setattr( setattr(