mirror of
https://github.com/gumyr/build123d.git
synced 2025-12-06 02:30:55 -08:00
Completed parameterization
This commit is contained in:
parent
c53ee55a76
commit
b0876a0005
1 changed files with 73 additions and 57 deletions
|
|
@ -34,15 +34,15 @@ license:
|
|||
import copy
|
||||
from airfoils import Airfoil
|
||||
from build123d import *
|
||||
from bd_warehouse.fastener import *
|
||||
from bd_warehouse.thread import *
|
||||
from bd_warehouse.fastener import ClearanceHole, CounterSunkScrew
|
||||
from bd_warehouse.thread import IsoThread
|
||||
from ocp_vscode import show, set_defaults, Camera
|
||||
|
||||
set_defaults(reset_camera=Camera.CENTER)
|
||||
|
||||
nuke_diameter = 10 * CM
|
||||
thickness = 2
|
||||
multipart_fins = True
|
||||
DIAMETER = 10 * CM
|
||||
THICKNESS = 2
|
||||
MULTIPART_FINS = True
|
||||
|
||||
#
|
||||
# -------- Core Nuke Shape --------
|
||||
|
|
@ -50,11 +50,11 @@ multipart_fins = True
|
|||
airfoil = Airfoil.NACA4("0045")
|
||||
aero_pnts = [Vector(p) for p in zip(airfoil._x_upper, airfoil._y_upper)]
|
||||
aero_pnts_max_y = max(p.Y for p in aero_pnts)
|
||||
aero_pnts_scaled = [p * (nuke_diameter / 2) / aero_pnts_max_y for p in aero_pnts]
|
||||
aero_pnts_scaled = [p * (DIAMETER / 2) / aero_pnts_max_y for p in aero_pnts]
|
||||
|
||||
with BuildPart() as nuke_core:
|
||||
with BuildSketch(
|
||||
Plane((0, 0, 1.87 * nuke_diameter), x_dir=(0, 0, -1), z_dir=(0, 1, 0))
|
||||
Plane((0, 0, 1.87 * DIAMETER), x_dir=(0, 0, -1), z_dir=(0, 1, 0))
|
||||
) as nuke_profile:
|
||||
with BuildLine() as nuke_outline:
|
||||
aero = Spline(*aero_pnts_scaled[12:80]) # 200 points total
|
||||
|
|
@ -66,7 +66,7 @@ with BuildPart() as nuke_core:
|
|||
)
|
||||
tail = Spline(
|
||||
aero @ 1,
|
||||
(1.54 * nuke_diameter, 0),
|
||||
(1.54 * DIAMETER, 0),
|
||||
tangents=[aero % 1, (0, -1)],
|
||||
tangent_scalars=(1.25, 0.80),
|
||||
)
|
||||
|
|
@ -81,14 +81,14 @@ with BuildPart() as nuke_core:
|
|||
with Locations(line @ param):
|
||||
Rectangle(
|
||||
2 * MM,
|
||||
thickness,
|
||||
THICKNESS,
|
||||
rotation=line.tangent_angle_at(param),
|
||||
mode=Mode.SUBTRACT,
|
||||
)
|
||||
with Locations(tail @ 0.45):
|
||||
Rectangle(
|
||||
5 * MM,
|
||||
thickness,
|
||||
THICKNESS,
|
||||
rotation=tail.tangent_angle_at(0.45),
|
||||
)
|
||||
revolve()
|
||||
|
|
@ -102,9 +102,10 @@ with BuildPart() as nuke_core:
|
|||
#
|
||||
# -------- Warning Ring --------
|
||||
#
|
||||
warning_ring_face = nuke_core.faces().sort_by(Axis.Z)[-15]
|
||||
warning_ring_face = nuke_core_faces[-15]
|
||||
warning_ring = thicken(warning_ring_face, -1 * MM)
|
||||
warning_ring.color = Color("Gold")
|
||||
warning_ring.label = "warning ring"
|
||||
|
||||
#
|
||||
# -------- Fins --------
|
||||
|
|
@ -114,59 +115,71 @@ warning_ring.color = Color("Gold")
|
|||
fin_screw = CounterSunkScrew(size="M1.4-0.3", length=3 * MM, fastener_type="iso2009")
|
||||
# fin_screw_head = split(fin_screw, Plane.XY.offset(-fin_screw.head_height))
|
||||
fin_screw.color = Color(0xC0C0C0) # Silver
|
||||
fin_screw.label = "fin screw"
|
||||
|
||||
with BuildPart() as fins:
|
||||
|
||||
with BuildPart() as fin_outer_ring:
|
||||
with BuildSketch() as bs0:
|
||||
Circle(nuke_diameter / 2)
|
||||
Circle(nuke_diameter / 2 - thickness, mode=Mode.SUBTRACT)
|
||||
Circle(DIAMETER / 2)
|
||||
Circle(DIAMETER / 2 - THICKNESS, mode=Mode.SUBTRACT)
|
||||
# Only want 1/4 of the ring
|
||||
Rectangle(
|
||||
2 * nuke_diameter,
|
||||
2 * nuke_diameter,
|
||||
2 * DIAMETER,
|
||||
2 * DIAMETER,
|
||||
align=Align.MIN,
|
||||
rotation=45,
|
||||
mode=Mode.INTERSECT,
|
||||
)
|
||||
extrude(amount=28)
|
||||
with BuildSketch(Plane.XZ) as bs1:
|
||||
Trapezoid(50, 19, 84, align=(Align.CENTER, Align.MIN))
|
||||
fillet(bs1.vertices().group_by(Axis.Y)[-1], 4 * MM)
|
||||
Trapezoid(
|
||||
DIAMETER / 2,
|
||||
DIAMETER * 0.19,
|
||||
84,
|
||||
align=(Align.CENTER, Align.MIN),
|
||||
)
|
||||
fillet(bs1.vertices().group_by(Axis.Y)[-1], DIAMETER * 0.04)
|
||||
projection = project(mode=Mode.PRIVATE).faces().sort_by(Axis.Y)[1]
|
||||
thicken(projection, amount=-thickness, mode=Mode.SUBTRACT)
|
||||
thicken(projection, amount=-THICKNESS, mode=Mode.SUBTRACT)
|
||||
# Replace to create the full ring
|
||||
with PolarLocations(0, 3, start_angle=90, angular_range=270):
|
||||
add(fin_outer_ring.part)
|
||||
|
||||
# Used to position featues below
|
||||
outer_ring_face = fin_outer_ring.faces().sort_by(SortBy.AREA)[-1]
|
||||
|
||||
with BuildPart() as fin_inner_ring:
|
||||
with BuildSketch(Plane.XY.offset(5.5)) as bs0:
|
||||
Circle(18)
|
||||
Circle(18 - thickness, mode=Mode.SUBTRACT)
|
||||
extrude(amount=15)
|
||||
with BuildSketch(Plane.XY.offset(DIAMETER * 0.055)):
|
||||
Circle(DIAMETER * 0.18)
|
||||
Circle(DIAMETER * 0.18 - THICKNESS, mode=Mode.SUBTRACT)
|
||||
extrude(amount=DIAMETER * 0.15)
|
||||
|
||||
with BuildPart() as fin_supports:
|
||||
with BuildSketch(Plane.XY.offset(10)) as fin_support_plan:
|
||||
Rectangle(53 * 2, thickness, rotation=-45)
|
||||
Rectangle(53 * 2, thickness, rotation=45)
|
||||
Circle(50 - thickness, mode=Mode.INTERSECT)
|
||||
Circle(18, mode=Mode.SUBTRACT)
|
||||
Rectangle(DIAMETER + 2 * THICKNESS, THICKNESS, rotation=-45)
|
||||
Rectangle(DIAMETER + 2 * THICKNESS, THICKNESS, rotation=45)
|
||||
Circle(DIAMETER / 2 - THICKNESS, mode=Mode.INTERSECT)
|
||||
Circle(DIAMETER * 0.18, mode=Mode.SUBTRACT)
|
||||
extrude(until=Until.NEXT, target=nuke_core.part)
|
||||
with BuildSketch(Plane.XZ) as support_trim:
|
||||
Trapezoid(176, 57, 45, align=(Align.CENTER, Align.MIN))
|
||||
Trapezoid(
|
||||
DIAMETER * 1.76, DIAMETER * 0.57, 45, align=(Align.CENTER, Align.MIN)
|
||||
)
|
||||
split(bisect_by=Plane.YZ)
|
||||
revolve(mode=Mode.INTERSECT)
|
||||
fin_contacts = fin_supports.faces().group_by(Axis.Z)[-2]
|
||||
fin_tabs = extrude(fin_contacts, amount=1 * MM, dir=(0, 0, 1))
|
||||
fin_tabs = extrude(fin_contacts, amount=THICKNESS / 2, dir=(0, 0, 1))
|
||||
|
||||
support_fillet_edges = (
|
||||
fins.edges().filter_by(Axis.Z).filter_by_position(Axis.Z, 0.0, 27.5)
|
||||
fins.edges().filter_by(Axis.Z).filter_by_position(Axis.Z, 0.0, DIAMETER * 0.275)
|
||||
)
|
||||
fillet(support_fillet_edges, 6 * MM)
|
||||
if multipart_fins:
|
||||
fin_plan = section(section_by=Plane.XY.offset(28 + 10))
|
||||
red_fins = extrude(fin_plan, amount=-28, mode=Mode.SUBTRACT)
|
||||
fillet(support_fillet_edges, DIAMETER * 0.06)
|
||||
if MULTIPART_FINS:
|
||||
fin_plan = section(section_by=Plane.XY.offset(DIAMETER * (0.28 + 0.10)))
|
||||
red_fins = extrude(fin_plan, amount=-DIAMETER * 0.28, mode=Mode.SUBTRACT)
|
||||
red_fins.color = Color("FireBrick")
|
||||
red_fins.label = "red fins"
|
||||
|
||||
screw_uv_values = [(0.015, 0.15), (0.015, 0.55), (0.985, 0.15), (0.985, 0.55)]
|
||||
fin_screw_locs = []
|
||||
|
|
@ -179,9 +192,10 @@ with BuildPart() as fins:
|
|||
)
|
||||
|
||||
with Locations(fin_screw_locs):
|
||||
ClearanceHole(fin_screw, depth=3 * MM, counter_sunk=True, fit="Close")
|
||||
ClearanceHole(fin_screw, depth=THICKNESS * 1.5, counter_sunk=True, fit="Close")
|
||||
|
||||
fins.part.color = Color("OliveDrab")
|
||||
fins.part.label = "fins"
|
||||
|
||||
#
|
||||
# -------- Nose --------
|
||||
|
|
@ -191,6 +205,7 @@ fins.part.color = Color("OliveDrab")
|
|||
nose_screw = CounterSunkScrew(size="M3-0.5", length=10 * MM, fastener_type="iso14582")
|
||||
nose_screw_head = split(nose_screw, Plane.XY.offset(-nose_screw.head_height))
|
||||
nose_screw_head.color = Color(0xC0C0C0) # Silver
|
||||
nose_screw_head.label = "nose screw"
|
||||
|
||||
with BuildPart() as nose:
|
||||
add(nuke_core.part)
|
||||
|
|
@ -199,44 +214,45 @@ with BuildPart() as nose:
|
|||
nose.edges().group_by(Axis.Z)[0].sort_by(SortBy.LENGTH)
|
||||
)
|
||||
nose_face = nose.faces().sort_by(SortBy.AREA)[-1]
|
||||
|
||||
# The edge isn't of type CIRCLE (even though it is) so calculate radius
|
||||
bottom_inside_edge_radius = bottom_inside_edge.bounding_box().size.X / 2
|
||||
|
||||
# Thread
|
||||
with Locations((0, 0, bottom_edge.center().Z - 7 * MM)):
|
||||
with Locations((0, 0, bottom_edge.center().Z - (DIAMETER * 0.06 + 1 * MM))):
|
||||
nose_thread = IsoThread(
|
||||
major_diameter=2 * (bottom_edge.radius - 1 * MM),
|
||||
pitch=2 * MM,
|
||||
length=6 * MM,
|
||||
length=DIAMETER * 0.06,
|
||||
external=True,
|
||||
end_finishes=("fade", "square"),
|
||||
)
|
||||
with BuildSketch(Plane.XY.offset(bottom_edge.center().Z)):
|
||||
Circle(bottom_inside_edge_radius)
|
||||
Circle(nose_thread.min_radius - thickness, mode=Mode.SUBTRACT)
|
||||
Circle(nose_thread.min_radius - THICKNESS, mode=Mode.SUBTRACT)
|
||||
extrude(until=Until.NEXT)
|
||||
with BuildSketch(Plane.XY.offset(bottom_edge.center().Z)):
|
||||
Circle(bottom_edge.radius)
|
||||
cap = extrude(amount=-1 * MM, taper=45)
|
||||
with BuildSketch(cap.faces().sort_by(Axis.Z)[0]):
|
||||
Circle(nose_thread.min_radius - thickness)
|
||||
Circle(nose_thread.min_radius - THICKNESS)
|
||||
extrude(amount=-1 * MM, mode=Mode.SUBTRACT)
|
||||
with BuildSketch(cap.faces().sort_by(Axis.Z)[0]):
|
||||
Circle(nose_thread.min_radius)
|
||||
Circle(nose_thread.min_radius - thickness, mode=Mode.SUBTRACT)
|
||||
extrude(amount=6 * MM)
|
||||
Circle(nose_thread.min_radius - THICKNESS, mode=Mode.SUBTRACT)
|
||||
extrude(amount=DIAMETER * 0.06)
|
||||
|
||||
# Nose cone screws
|
||||
nose_screw_ref_pnt = nose_face.position_at(0.0, 0.3)
|
||||
nose_screw_ref_nrm = nose_face.normal_at(nose_screw_ref_pnt)
|
||||
nose_screw_locs = [
|
||||
Rot(0, 0, a) * Location(Plane(nose_screw_ref_pnt, z_dir=nose_screw_ref_nrm))
|
||||
for a in range(0, 360, 45)
|
||||
Rot(0, 0, angle) * Location(Plane(nose_screw_ref_pnt, z_dir=nose_screw_ref_nrm))
|
||||
for angle in range(0, 360, 45)
|
||||
]
|
||||
with Locations(nose_screw_locs):
|
||||
ClearanceHole(nose_screw, fit="Close")
|
||||
|
||||
nose.part.color = Color("FireBrick")
|
||||
nose.part.label = "nose"
|
||||
|
||||
#
|
||||
# -------- Final Nuke Shape --------
|
||||
|
|
@ -244,16 +260,18 @@ nose.part.color = Color("FireBrick")
|
|||
top_screw = CounterSunkScrew(size="M4-0.7", length=10 * MM, fastener_type="iso14582")
|
||||
top_screw_head = split(top_screw, Plane.XY.offset(-top_screw.head_height))
|
||||
top_screw_head.color = Color(0xC0C0C0) # Silver
|
||||
top_screw_head.label = "top screw"
|
||||
|
||||
middle_screw = CounterSunkScrew(size="M6-1", length=10 * MM, fastener_type="iso14582")
|
||||
middle_screw_head = split(middle_screw, Plane.XY.offset(-middle_screw.head_height))
|
||||
middle_screw_head.color = Color(0xC0C0C0) # Silver
|
||||
middle_screw_head.label = "middle screw"
|
||||
|
||||
# Internal thread
|
||||
nose_thread = IsoThread(
|
||||
major_diameter=2 * (bottom_edge.radius - 1 * MM),
|
||||
pitch=2 * MM,
|
||||
length=6 * MM,
|
||||
length=DIAMETER * 0.06,
|
||||
external=False,
|
||||
end_finishes=("square", "fade"),
|
||||
)
|
||||
|
|
@ -262,6 +280,7 @@ with BuildPart() as nuke:
|
|||
add(nuke_core.part)
|
||||
split(bisect_by=Plane.XY.offset(nuke_body_limits[1]), keep=Keep.BOTTOM)
|
||||
|
||||
# Create the thread
|
||||
top_edge = (
|
||||
nuke.edges()
|
||||
.filter_by(GeomType.CIRCLE)
|
||||
|
|
@ -270,11 +289,11 @@ with BuildPart() as nuke:
|
|||
)
|
||||
with BuildSketch(Plane.XY.offset(top_edge.center().Z)):
|
||||
Circle(top_edge.radius)
|
||||
extrude(amount=-6 * MM, taper=150)
|
||||
extrude(amount=-DIAMETER * 0.06, taper=150)
|
||||
with BuildSketch(Plane.XY.offset(top_edge.center().Z)):
|
||||
Circle(nose_thread.major_diameter / 2 - 0.02 * MM)
|
||||
extrude(amount=-6 * MM, mode=Mode.SUBTRACT)
|
||||
with Locations((0, 0, nuke_body_limits[1] - 6 * MM)):
|
||||
Circle(nose_thread.major_diameter / 2 - 0.02 * MM) # small fudge required
|
||||
extrude(amount=-DIAMETER * 0.06, mode=Mode.SUBTRACT)
|
||||
with Locations((0, 0, nuke_body_limits[1] - DIAMETER * 0.06)):
|
||||
add(nose_thread)
|
||||
|
||||
# Create sockets for the fins
|
||||
|
|
@ -313,18 +332,19 @@ with BuildPart() as nuke:
|
|||
normal = whistle_ring_face.normal_at(*whistle_uv)
|
||||
origin = whistle_ring_face.position_at(*whistle_uv)
|
||||
pln = Plane(
|
||||
origin=origin + Vector(normal.X, normal.Y, -0.5) * 2 * MM,
|
||||
origin=origin + Vector(normal.X, normal.Y, -0.5) * DIAMETER * 0.02,
|
||||
z_dir=normal + Vector(0, 0, 0.6),
|
||||
)
|
||||
with BuildSketch(pln):
|
||||
RectangleRounded(8 * MM, 8 * MM, 1 * MM)
|
||||
Rectangle(6 * MM, 6 * MM, mode=Mode.SUBTRACT)
|
||||
RectangleRounded(DIAMETER * 0.08, DIAMETER * 0.08, DIAMETER * 0.01)
|
||||
Rectangle(DIAMETER * 0.06, DIAMETER * 0.06, mode=Mode.SUBTRACT)
|
||||
whistle = extrude(until=Until.PREVIOUS, dir=normal + Vector(0, 0, 1))
|
||||
whistle_flipped = mirror(whistle, about=Plane.XZ)
|
||||
mirror(whistle, about=Plane.YZ.rotated((0, 0, 22.5)))
|
||||
mirror(whistle_flipped, about=Plane.YZ.rotated((0, 0, -22.5)))
|
||||
|
||||
nuke.part.color = Color("OliveDrab")
|
||||
nuke.part.label = "nuke"
|
||||
|
||||
#
|
||||
# -------- Final Assembly --------
|
||||
|
|
@ -336,13 +356,9 @@ components = (
|
|||
+ [copy.copy(middle_screw_head).locate(l) for l in middle_face_screw_locs]
|
||||
+ [copy.copy(fin_screw).locate(l) for l in fin_screw_locs]
|
||||
)
|
||||
if multipart_fins:
|
||||
if MULTIPART_FINS:
|
||||
components.append(red_fins)
|
||||
|
||||
nuke_assembly = Compound(children=components)
|
||||
|
||||
show(
|
||||
nuke_assembly,
|
||||
center_grid=True,
|
||||
names=["nuke_assembly"],
|
||||
)
|
||||
show(nuke_assembly, center_grid=True, names=["nuke_assembly"])
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue