diff --git a/nhf/materials.py b/nhf/materials.py index bc172c3..909e771 100644 --- a/nhf/materials.py +++ b/nhf/materials.py @@ -84,6 +84,7 @@ class Material(Enum): ACRYLIC_TRANSLUSCENT = 1.18, _color('ivory2', 0.8) ACRYLIC_TRANSPARENT = 1.18, _color('ghostwhite', 0.5) STEEL_SPRING = 7.8, _color('gray', 0.8) + ALUMINUM = 2.7, _color('gray', 0.6) def __init__(self, density: float, color: Cq.Color): self.density = density diff --git a/nhf/touhou/__init__.py b/nhf/touhou/__init__.py new file mode 100644 index 0000000..e5a0d9b --- /dev/null +++ b/nhf/touhou/__init__.py @@ -0,0 +1 @@ +#!/usr/bin/env python3 diff --git a/nhf/touhou/yasaka_kanako/__init__.py b/nhf/touhou/yasaka_kanako/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/nhf/touhou/yasaka_kanako/onbashira.py b/nhf/touhou/yasaka_kanako/onbashira.py new file mode 100644 index 0000000..4169081 --- /dev/null +++ b/nhf/touhou/yasaka_kanako/onbashira.py @@ -0,0 +1,79 @@ +from nhf.build import Model, TargetKind, target, assembly, submodel +from nhf.materials import Role, Material +import nhf.utils + +import math +from dataclasses import dataclass +import cadquery as Cq + +@dataclass +class Onbashira(Model): + + n_side: int = 6 + # Dimensions of each side panel + side_width: float = 200.0 + side_length: float = 600.0 + + side_thickness: float = 25.4 / 8 + + material_side: Material = Material.WOOD_BIRCH + material_brace: Material = Material.ALUMINUM + + def __post_init__(self): + assert self.n_side >= 3 + + @property + def angle_side(self) -> float: + return 360 / self.n_side + @property + def angle_dihedral(self) -> float: + return 180 - self.angle_side + @property + def barrel_radius(self) -> float: + """ + Calculate radius of the barrel to the centre + """ + return self.side_width / 2 / math.tan(math.radians(self.angle_side / 2)) + + @target(name="side-panel", kind=TargetKind.DXF) + def profile_side_panel(self) -> Cq.Sketch: + return ( + Cq.Sketch() + .rect(self.side_width, self.side_length) + ) + + def side_panel(self) -> Cq.Workplane: + w = self.side_width + l = self.side_length + result = ( + Cq.Workplane() + .placeSketch(self.profile_side_panel()) + .extrude(self.side_thickness) + ) + intersector = ( + Cq.Workplane('XZ') + .polyline([ + (-w/2, 0), + (w/2, 0), + (0, self.barrel_radius), + ]) + .close() + .extrude(l) + .translate(Cq.Vector(0, l/2,0)) + ) + # Intersect the side panel + return result * intersector + + def assembly(self) -> Cq.Assembly: + a = Cq.Assembly() + side = self.side_panel() + r = self.barrel_radius + for i in range(6): + a = a.addS( + side, + name=f"side{i}", + material=self.material_side, + role=Role.STRUCTURE | Role.DECORATION, + loc=Cq.Location(0,0,0,0,i*60,0) * Cq.Location(0,0,-r) + ) + return a