From 396dd997e0ce178a6e7e960d44570eba00bc7f1c Mon Sep 17 00:00:00 2001 From: Leni Aniva Date: Sun, 23 Feb 2025 22:01:45 -0800 Subject: [PATCH] New Eiki crown design using conformal mapping --- nhf/touhou/shiki_eiki/crown.py | 50 ++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/nhf/touhou/shiki_eiki/crown.py b/nhf/touhou/shiki_eiki/crown.py index 4c4c219..2dcb300 100644 --- a/nhf/touhou/shiki_eiki/crown.py +++ b/nhf/touhou/shiki_eiki/crown.py @@ -357,6 +357,10 @@ class Crown(Model): return sketch.assemble() def side_guard(self) -> Cq.Workplane: + """ + Constructs the side guard using a cone. Via Gauss's Theorema Egregium, + the surface of the cone can be deformed into a plane. + """ angle = 360 / 5 outer = Cq.Solid.makeCone( radius1=self.radius_lower + self.side_guard_thickness, @@ -399,7 +403,48 @@ class Crown(Model): ) return shell * profile - channel + def front_surrogate(self) -> Cq.Workplane: + """ + Create a surrogate cylindrical section structure for the front since we + cannot bend extrusions + """ + angle = 360 / 5 + outer = Cq.Solid.makeCone( + radius1=self.radius_lower + self.thickness, + radius2=self.radius_upper + self.thickness, + height=self.height, + angleDegrees=angle, + ) + 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() + ) + return shell * profile + def assembly(self) -> Cq.Assembly: + """ + New assembly using conformal mapping on the cone. + """ side_guard = self.side_guard() a = Cq.Assembly() for i in range(1,5): @@ -409,6 +454,11 @@ class Crown(Model): material=self.material_side, loc=Cq.Location(rz=i*360/5) ) + a.addS( + self.front_surrogate(), + name="front", + material=self.material, + ) return a def old_assembly(self) -> Cq.Assembly: