Spaces:
Sleeping
Sleeping
| from __future__ import annotations | |
| import argparse | |
| import json | |
| from pathlib import Path | |
| import cadquery as cq | |
| from cadquery import exporters | |
| def build_fixture() -> cq.Workplane: | |
| base_width = 50 | |
| base_height = 80 | |
| base_thickness = 6 | |
| corner_radius = 4 | |
| hole_dia = 5.2 | |
| csk_dia = 10 | |
| csk_angle = 82 | |
| hole_inset_x = 10 | |
| hole_inset_y = 12 | |
| shaft_width = 14 | |
| shaft_depth = 12 | |
| shaft_length = 35 | |
| hook_inner_radius = 16 | |
| hook_outer_radius = hook_inner_radius + shaft_depth | |
| gusset_thickness = 6 | |
| bottom_gusset_length = 25 | |
| bottom_gusset_height = 18 | |
| top_gusset_length = 15 | |
| top_gusset_height = 12 | |
| base = ( | |
| cq.Workplane("XY") | |
| .box(base_width, base_height, base_thickness) | |
| .edges("|Z") | |
| .fillet(corner_radius) | |
| ) | |
| hx = base_width / 2 - hole_inset_x | |
| hy = base_height / 2 - hole_inset_y | |
| pts = [(hx, hy), (-hx, hy), (hx, -hy), (-hx, -hy)] | |
| base = ( | |
| base.faces(">Z") | |
| .workplane() | |
| .pushPoints(pts) | |
| .cskHole(diameter=hole_dia, cskDiameter=csk_dia, cskAngle=csk_angle) | |
| ) | |
| z_start = base_thickness / 2 | |
| z_arc_center = z_start + shaft_length | |
| y_inner_start = shaft_depth / 2 | |
| y_outer_start = -shaft_depth / 2 | |
| hook = ( | |
| cq.Workplane("YZ") | |
| .moveTo(y_outer_start, z_start) | |
| .lineTo(y_outer_start, z_arc_center) | |
| .threePointArc( | |
| (y_outer_start + hook_outer_radius, z_arc_center + hook_outer_radius), | |
| (y_outer_start + 2 * hook_outer_radius, z_arc_center), | |
| ) | |
| .threePointArc( | |
| (y_outer_start + 2 * hook_outer_radius - shaft_depth / 2, z_arc_center - shaft_depth / 2), | |
| (y_outer_start + 2 * hook_outer_radius - shaft_depth, z_arc_center), | |
| ) | |
| .threePointArc( | |
| (y_inner_start + hook_inner_radius, z_arc_center + hook_inner_radius), | |
| (y_inner_start, z_arc_center), | |
| ) | |
| .lineTo(y_inner_start, z_start) | |
| .close() | |
| .extrude(shaft_width / 2, both=True) | |
| ) | |
| bottom_gusset = ( | |
| cq.Workplane("YZ") | |
| .moveTo(y_outer_start, z_start) | |
| .lineTo(y_outer_start - bottom_gusset_length, z_start) | |
| .lineTo(y_outer_start, z_start + bottom_gusset_height) | |
| .close() | |
| .extrude(gusset_thickness / 2, both=True) | |
| ) | |
| top_gusset = ( | |
| cq.Workplane("YZ") | |
| .moveTo(y_inner_start, z_start) | |
| .lineTo(y_inner_start + top_gusset_length, z_start) | |
| .lineTo(y_inner_start, z_start + top_gusset_height) | |
| .close() | |
| .extrude(gusset_thickness / 2, both=True) | |
| ) | |
| return base.union(hook).union(bottom_gusset).union(top_gusset) | |
| def main() -> None: | |
| parser = argparse.ArgumentParser(description="Build the CadQuery heavy-duty hook sample.") | |
| parser.add_argument("--out-dir", required=True) | |
| args = parser.parse_args() | |
| out_dir = Path(args.out_dir) | |
| out_dir.mkdir(parents=True, exist_ok=True) | |
| stl_path = out_dir / "heavy_duty_hook.stl" | |
| fixture = build_fixture() | |
| exporters.export(fixture, str(stl_path)) | |
| bbox = fixture.val().BoundingBox() | |
| print( | |
| json.dumps( | |
| { | |
| "name": "Heavy_Duty_Hook", | |
| "stl_path": str(stl_path), | |
| "bounding_box": { | |
| "xlen": bbox.xlen, | |
| "ylen": bbox.ylen, | |
| "zlen": bbox.zlen, | |
| "xmin": bbox.xmin, | |
| "xmax": bbox.xmax, | |
| "ymin": bbox.ymin, | |
| "ymax": bbox.ymax, | |
| "zmin": bbox.zmin, | |
| "zmax": bbox.zmax, | |
| }, | |
| "cadquery_features": [ | |
| "filleted base plate", | |
| "four countersunk mounting holes", | |
| "sketched curved J hook profile", | |
| "bottom triangular gusset", | |
| "top triangular gusset", | |
| "single CadQuery unioned fixture", | |
| ], | |
| } | |
| ) | |
| ) | |
| if __name__ == "__main__": | |
| main() | |