diff --git a/nhf/touhou/shiki_eiki/crown.py b/nhf/touhou/shiki_eiki/crown.py index 6bc3ab6..4c4c219 100644 --- a/nhf/touhou/shiki_eiki/crown.py +++ b/nhf/touhou/shiki_eiki/crown.py @@ -11,21 +11,27 @@ class Crown(Model): facets: int = 5 # Lower circumference base_circ: float = 538.0 - # Upper circumference + # Upper circumference, at the middle tilt_circ: float = 640.0 + # Total height height: float = 120.0 margin: float = 10.0 thickness: float = 0.4 # 26 Gauge + side_guard_thickness: float = 15.0 + side_guard_channel_radius: float = 90 + side_guard_channel_height: float = 10 material: Material = Material.METAL_BRASS + material_side: Material = Material.PLASTIC_PLA def __post_init__(self): super().__init__(name="crown") assert self.tilt_circ > self.base_circ assert self.facet_width_upper / 2 > self.height / 2, "Top angle must be > 90 degrees" + assert self.side_guard_channel_radius > self.radius_lower @property def facet_width_lower(self): @@ -33,6 +39,15 @@ class Crown(Model): @property def facet_width_upper(self): return self.tilt_circ / self.facets + @property + def radius_lower(self): + return self.base_circ / (2 * math.pi) + @property + def radius_middle(self): + return self.tilt_circ / (2 * math.pi) + @property + def radius_upper(self): + return (self.tilt_circ + (self.tilt_circ - self.base_circ)) / (2 * math.pi) def profile_base(self) -> Cq.Sketch: # Generate the pentagonal shape @@ -342,16 +357,61 @@ class Crown(Model): return sketch.assemble() def side_guard(self) -> Cq.Workplane: - rb = self.base_circ / (2 * math.pi) - rt = self.tilt_circ / (2 * math.pi) + angle = 360 / 5 outer = Cq.Solid.makeCone( - radius1=rb, - radius2=rt, + radius1=self.radius_lower + self.side_guard_thickness, + radius2=self.radius_upper + self.side_guard_thickness, height=self.height, + angleDegrees=angle, ) - return outer + inner = Cq.Solid.makeCone( + radius1=self.radius_lower, + radius2=self.radius_upper, + height=self.height, + angleDegrees=angle, + ) + shell = ( + outer.cut(inner) + .rotate((0,0,0), (0,0,1), -angle/2) + ) + dx = math.sin(math.radians(angle / 2)) * self.radius_middle + profile = ( + Cq.Workplane('YZ') + .polyline([ + (0, self.height), + (-dx, self.height / 2), + (-dx, 0), + (dx, 0), + (dx, self.height / 2), + ]) + .close() + .extrude(self.radius_upper + self.side_guard_thickness) + .val() + ) + channel = ( + Cq.Solid.makeCylinder( + radius=self.side_guard_channel_radius + 1.0, + height=self.side_guard_channel_height, + ) - Cq.Solid.makeCylinder( + radius=self.side_guard_channel_radius, + height=self.side_guard_channel_height, + ) + ) + return shell * profile - channel def assembly(self) -> Cq.Assembly: + side_guard = self.side_guard() + a = Cq.Assembly() + for i in range(1,5): + a = a.addS( + side_guard, + name=f"side-{i}", + material=self.material_side, + loc=Cq.Location(rz=i*360/5) + ) + return a + + def old_assembly(self) -> Cq.Assembly: front = ( Cq.Workplane('XY') .placeSketch(self.profile_front())