From eb8a48fe7789b57d03a32ce7ff9de2e2f0087111 Mon Sep 17 00:00:00 2001 From: Leni Aniva Date: Sun, 23 Jun 2024 22:27:15 -0700 Subject: [PATCH] feat: Harness assembly --- nhf/__init__.py | 1 + nhf/materials.py | 18 ++++ nhf/touhou/houjuu_nue/__init__.py | 152 ++++++++++++++++++++++++++---- nhf/touhou/houjuu_nue/test.py | 3 + 4 files changed, 155 insertions(+), 19 deletions(-) create mode 100644 nhf/materials.py diff --git a/nhf/__init__.py b/nhf/__init__.py index e69de29..2175f24 100644 --- a/nhf/__init__.py +++ b/nhf/__init__.py @@ -0,0 +1 @@ +from nhf.materials import Material diff --git a/nhf/materials.py b/nhf/materials.py new file mode 100644 index 0000000..7ca621b --- /dev/null +++ b/nhf/materials.py @@ -0,0 +1,18 @@ +""" +A catalog of material properties +""" +from enum import Enum +import cadquery as Cq + +def _color(name: str, alpha: float) -> Cq.Color: + r, g, b, _ = Cq.Color(name).toTuple() + return Cq.Color(r, g, b, alpha) + +class Material(Enum): + + WOOD_BIRCH = 0.8, _color('bisque', 0.9) + PLASTIC_PLA = 0.5, _color('azure3', 0.6) + + def __init__(self, density: float, color: Cq.Color): + self.density = density + self.color = color diff --git a/nhf/touhou/houjuu_nue/__init__.py b/nhf/touhou/houjuu_nue/__init__.py index 8d2c0c8..7fd08e7 100644 --- a/nhf/touhou/houjuu_nue/__init__.py +++ b/nhf/touhou/houjuu_nue/__init__.py @@ -2,6 +2,7 @@ from dataclasses import dataclass import unittest import cadquery as Cq import nhf.joints +from nhf import Material @dataclass(frozen=True) class Parameters: @@ -11,8 +12,39 @@ class Parameters: """ panel_thickness: float = 25.4 / 16 + # Harness + harness_thickness: float = 25.4 / 8 + harness_width = 300 + harness_height = 400 + harness_fillet = 10 + + harness_wing_base_pos = [ + ("r1", 70, 150), + ("l1", -70, 150), + ("r2", 100, 0), + ("l2", -100, 0), + ("r3", 70, -150), + ("l3", -70, -150), + ] + + # Holes drilled onto harness for attachment with HS joint + harness_to_wing_base_hole_diam = 6 + # Wing root properties """ + The Houjuu-Scarlett joint mechanism at the base of the wing + """ + hs_joint_base_width = 85 + hs_joint_base_thickness = 10 + hs_joint_ring_thickness = 5 + hs_joint_tooth_height = 10 + hs_joint_radius = 30 + hs_joint_radius_inner = 20 + hs_joint_corner_fillet = 5 + hs_joint_corner_cbore_diam = 12 + hs_joint_corner_cbore_depth = 12 + hs_joint_corner_inset = 15 + """ Radius of the mounting mechanism of the wing root. This is constrained by the size of the harness. """ @@ -26,26 +58,77 @@ class Parameters: wing_r2_height = 100 wing_r3_height = 100 - """ - The Houjuu-Scarlett joint mechanism at the base of the wing - """ - hs_joint_base_width = 85 - hs_joint_base_thickness = 10 - hs_joint_ring_thickness = 10 - hs_joint_tooth_height = 10 - hs_joint_radius = 30 - hs_joint_radius_inner = 20 - hs_joint_corner_fillet = 5 - hs_joint_corner_cbore_diam = 12 - hs_joint_corner_cbore_depth = 12 - hs_joint_corner_diam = 15 - hs_joint_corner_inset = 15 def print_geometries(self): return [ self.hs_joint_parent() ] + def harness_profile(self) -> Cq.Sketch: + """ + Creates the harness shape + """ + w, h = self.harness_width / 2, self.harness_height / 2 + sketch = ( + Cq.Sketch() + .polygon([ + (0.7 * w, h), + (w, 0), + (0.7 * w, -h), + (0.7 * -w, -h), + (-w, 0), + (0.7 * -w, h), + ]) + #.rect(self.harness_width, self.harness_height) + .vertices() + .fillet(self.harness_fillet) + ) + for tag, x, y in self.harness_wing_base_pos: + conn = [(px + x, py + y) for px, py in self.hs_joint_harness_conn()] + sketch = ( + sketch + .push(conn) + .tag(tag) + .circle(self.harness_to_wing_base_hole_diam / 2, mode='s') + .reset() + ) + return sketch + + def harness(self) -> Cq.Shape: + """ + Creates the harness shape + """ + result = ( + Cq.Workplane('XZ') + .placeSketch(self.harness_profile()) + .extrude(self.harness_thickness) + ) + result.faces(">Y").tag("mount") + plane = result.faces(">Y").workplane() + for tag, x, y in self.harness_wing_base_pos: + conn = [(px + x, py + y) for px, py in self.hs_joint_harness_conn()] + for i, (px, py) in enumerate(conn): + ( + plane + .moveTo(px, py) + .circle(1, forConstruction='True') + .edges() + .tag(f"{tag}_{i}") + ) + return result + + def hs_joint_harness_conn(self) -> list[tuple[int, int]]: + """ + Generates a set of points corresponding to the connectorss + """ + dx = self.hs_joint_base_width / 2 - self.hs_joint_corner_inset + return [ + (dx, dx), + (dx, -dx), + (-dx, -dx), + (-dx, dx), + ] + def hs_joint_parent(self): """ Parent part of the Houjuu-Scarlett joint, which is composed of a Hirth @@ -56,7 +139,6 @@ class Parameters: radius_inner=self.hs_joint_radius_inner, tooth_height=self.hs_joint_tooth_height, base_height=self.hs_joint_ring_thickness) - hole_rect_width = self.hs_joint_base_width - 2 * self.hs_joint_corner_inset hirth = ( hirth .faces("Z") .workplane() - .rect(hole_rect_width, hole_rect_width, forConstruction=True) - .vertices() + .pushPoints(conn) .cboreHole( - diameter=self.hs_joint_corner_diam, + diameter=self.harness_to_wing_base_hole_diam, cboreDiameter=self.hs_joint_corner_cbore_diam, cboreDepth=self.hs_joint_corner_cbore_depth) + ) + plane = result.faces(">Z").workplane(offset=-self.hs_joint_base_thickness) + for i, (px, py) in enumerate(conn): + ( + plane + .moveTo(px, py) + .circle(1, forConstruction='True') + .edges() + .tag(f"h{i}") + ) + result = ( + result .faces(">Z") .workplane() - .union(hirth.move((0, 0, self.hs_joint_base_thickness)), tol=0.1) + .union(hirth.move(Cq.Location((0, 0, self.hs_joint_base_thickness))), tol=0.1) .clean() ) + result.faces("