From b0876a0005b2e6499450766bad1b5d3273cafb97 Mon Sep 17 00:00:00 2001 From: gumyr Date: Wed, 3 Apr 2024 14:15:32 -0400 Subject: [PATCH] Completed parameterization --- examples/mini_nuke.py | 130 ++++++++++++++++++++++++------------------ 1 file changed, 73 insertions(+), 57 deletions(-) diff --git a/examples/mini_nuke.py b/examples/mini_nuke.py index 28397b2..7b4e0ca 100644 --- a/examples/mini_nuke.py +++ b/examples/mini_nuke.py @@ -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"])