137 lines
5.5 KiB
Python
137 lines
5.5 KiB
Python
"""Parametric eight-hole circular flange generated with build123d."""
|
|
|
|
from math import cos, radians, sin, tan
|
|
|
|
from build123d import Align, Box, BuildPart, Cone, Cylinder, Location, Locations, Mode
|
|
|
|
|
|
OUTER_DIAMETER_MM = 50.0
|
|
INNER_DIAMETER_MM = 20.0
|
|
THICKNESS_MM = 4.0
|
|
BOLT_HOLE_COUNT = 8
|
|
M3_CLEARANCE_DIAMETER_MM = 3.4
|
|
BOLT_CIRCLE_DIAMETER_MM = 40.0
|
|
M4_THREAD_SPEC = "M4"
|
|
M4_TAP_DRILL_DIAMETER_MM = 3.3
|
|
M4_THREAD_DEPTH_MM = 6.0
|
|
M4_THREAD_HOLE_CENTER_MM = (-6.104359972902419, -13.137483558259564)
|
|
M4_THREAD_HOLE_FACE_Z_MM = THICKNESS_MM
|
|
M4_THREAD_HOLE_DIRECTION = (0.0, 0.0, -1.0)
|
|
VIEWER_PATTERN_CENTER_MM = (8.077088362294017, 15.744119598589815)
|
|
VIEWER_PATTERN_HOLE_DIAMETER_MM = 2.0
|
|
VIEWER_PATTERN_ROWS = 2
|
|
VIEWER_PATTERN_COLUMNS = 2
|
|
VIEWER_PATTERN_PITCH_X_MM = 8.0
|
|
VIEWER_PATTERN_PITCH_Y_MM = 8.0
|
|
VIEWER_PATTERN_FACE_Z_MM = THICKNESS_MM
|
|
VIEWER_PATTERN_DIRECTION = (0.0, 0.0, -1.0)
|
|
VIEWER_COUNTERSINK_CENTER_MM = (-14.6034432889167, -4.110394299469192)
|
|
VIEWER_COUNTERSINK_HOLE_DIAMETER_MM = 3.0
|
|
VIEWER_COUNTERSINK_DIAMETER_MM = 6.0
|
|
VIEWER_COUNTERSINK_ANGLE_DEG = 90.0
|
|
VIEWER_COUNTERSINK_FACE_Z_MM = THICKNESS_MM
|
|
VIEWER_COUNTERSINK_DIRECTION = (0.0, 0.0, -1.0)
|
|
VIEWER_POCKET_CENTER_MM = (6.197199513379157, -14.374353062530322)
|
|
VIEWER_POCKET_WIDTH_MM = 10.0
|
|
VIEWER_POCKET_HEIGHT_MM = 6.0
|
|
VIEWER_POCKET_DEPTH_MM = 1.0
|
|
VIEWER_POCKET_FACE_Z_MM = THICKNESS_MM
|
|
VIEWER_POCKET_DIRECTION = (0.0, 0.0, -1.0)
|
|
|
|
|
|
def polar_point(radius: float, angle_degrees: float) -> tuple[float, float]:
|
|
angle = radians(angle_degrees)
|
|
return radius * cos(angle), radius * sin(angle)
|
|
|
|
|
|
def gen_step():
|
|
"""Return one STEP-ready flange solid in millimeters."""
|
|
with BuildPart() as flange:
|
|
Cylinder(
|
|
radius=OUTER_DIAMETER_MM / 2.0,
|
|
height=THICKNESS_MM,
|
|
align=(Align.CENTER, Align.CENTER, Align.MIN),
|
|
)
|
|
|
|
with Locations(Location((0.0, 0.0, -1.0))):
|
|
Cylinder(
|
|
radius=INNER_DIAMETER_MM / 2.0,
|
|
height=THICKNESS_MM + 2.0,
|
|
align=(Align.CENTER, Align.CENTER, Align.MIN),
|
|
mode=Mode.SUBTRACT,
|
|
)
|
|
|
|
for index in range(BOLT_HOLE_COUNT):
|
|
angle_degrees = 360.0 * index / BOLT_HOLE_COUNT
|
|
x_pos, y_pos = polar_point(BOLT_CIRCLE_DIAMETER_MM / 2.0, angle_degrees)
|
|
with Locations(Location((x_pos, y_pos, -1.0))):
|
|
Cylinder(
|
|
radius=M3_CLEARANCE_DIAMETER_MM / 2.0,
|
|
height=THICKNESS_MM + 2.0,
|
|
align=(Align.CENTER, Align.CENTER, Align.MIN),
|
|
mode=Mode.SUBTRACT,
|
|
)
|
|
|
|
m4_x_pos, m4_y_pos = M4_THREAD_HOLE_CENTER_MM
|
|
m4_cut_depth = min(M4_THREAD_DEPTH_MM, THICKNESS_MM)
|
|
with Locations(Location((m4_x_pos, m4_y_pos, M4_THREAD_HOLE_FACE_Z_MM - m4_cut_depth))):
|
|
Cylinder(
|
|
radius=M4_TAP_DRILL_DIAMETER_MM / 2.0,
|
|
height=m4_cut_depth + 1.0,
|
|
align=(Align.CENTER, Align.CENTER, Align.MIN),
|
|
mode=Mode.SUBTRACT,
|
|
)
|
|
|
|
pattern_center_x, pattern_center_y = VIEWER_PATTERN_CENTER_MM
|
|
pattern_start_x = pattern_center_x - (VIEWER_PATTERN_COLUMNS - 1) * VIEWER_PATTERN_PITCH_X_MM / 2.0
|
|
pattern_start_y = pattern_center_y - (VIEWER_PATTERN_ROWS - 1) * VIEWER_PATTERN_PITCH_Y_MM / 2.0
|
|
for row_index in range(VIEWER_PATTERN_ROWS):
|
|
for column_index in range(VIEWER_PATTERN_COLUMNS):
|
|
hole_x = pattern_start_x + column_index * VIEWER_PATTERN_PITCH_X_MM
|
|
hole_y = pattern_start_y + row_index * VIEWER_PATTERN_PITCH_Y_MM
|
|
with Locations(Location((hole_x, hole_y, -1.0))):
|
|
Cylinder(
|
|
radius=VIEWER_PATTERN_HOLE_DIAMETER_MM / 2.0,
|
|
height=THICKNESS_MM + 2.0,
|
|
align=(Align.CENTER, Align.CENTER, Align.MIN),
|
|
mode=Mode.SUBTRACT,
|
|
)
|
|
|
|
countersink_x, countersink_y = VIEWER_COUNTERSINK_CENTER_MM
|
|
countersink_radius = VIEWER_COUNTERSINK_DIAMETER_MM / 2.0
|
|
countersink_through_radius = VIEWER_COUNTERSINK_HOLE_DIAMETER_MM / 2.0
|
|
countersink_depth = (
|
|
countersink_radius - countersink_through_radius
|
|
) / tan(radians(VIEWER_COUNTERSINK_ANGLE_DEG / 2.0))
|
|
with Locations(Location((countersink_x, countersink_y, -1.0))):
|
|
Cylinder(
|
|
radius=countersink_through_radius,
|
|
height=THICKNESS_MM + 2.0,
|
|
align=(Align.CENTER, Align.CENTER, Align.MIN),
|
|
mode=Mode.SUBTRACT,
|
|
)
|
|
with Locations(
|
|
Location((countersink_x, countersink_y, VIEWER_COUNTERSINK_FACE_Z_MM - countersink_depth))
|
|
):
|
|
Cone(
|
|
countersink_through_radius,
|
|
countersink_radius,
|
|
countersink_depth + 0.05,
|
|
align=(Align.CENTER, Align.CENTER, Align.MIN),
|
|
mode=Mode.SUBTRACT,
|
|
)
|
|
|
|
pocket_x, pocket_y = VIEWER_POCKET_CENTER_MM
|
|
with Locations(Location((pocket_x, pocket_y, VIEWER_POCKET_FACE_Z_MM - VIEWER_POCKET_DEPTH_MM))):
|
|
Box(
|
|
VIEWER_POCKET_WIDTH_MM,
|
|
VIEWER_POCKET_HEIGHT_MM,
|
|
VIEWER_POCKET_DEPTH_MM + 0.05,
|
|
align=(Align.CENTER, Align.CENTER, Align.MIN),
|
|
mode=Mode.SUBTRACT,
|
|
)
|
|
|
|
part = flange.part
|
|
part.label = "flange_8x_m3_clearance_with_m4_tapped_hole_viewer_pattern_countersink_and_pocket"
|
|
return part
|