diff --git a/nhf/touhou/yasaka_kanako/onbashira.py b/nhf/touhou/yasaka_kanako/onbashira.py index c7e23ce..6ea555b 100644 --- a/nhf/touhou/yasaka_kanako/onbashira.py +++ b/nhf/touhou/yasaka_kanako/onbashira.py @@ -121,6 +121,8 @@ class Onbashira(Model): angle_joint_bolt_position: list[float] = field(default_factory=lambda: [ (40, 10), ]) + angle_joint_flange_thickness: float = 7.8 + angle_joint_flange_radius: float = 23.0 angle_joint_flange_extension: float = 23.0 angle_joint_extra_hole_offset: float = 20.0 @@ -160,9 +162,9 @@ class Onbashira(Model): stator_bind_radius: float = 135.0 handle_base_height: float = 10.0 - handle_thickness: float = 12.0 - handle_length: float = 80.0 - handle_height: float = 40.0 + handle_thickness: float = 17.0 + handle_length: float = 140.0 + handle_height: float = 50.0 motor: Motor = Motor() @@ -725,6 +727,32 @@ class Onbashira(Model): ) return a + def angle_joint_flange(self) -> Cq.Workplane: + th = math.pi / self.n_side + r = self.bulk_radius + flange = ( + Cq.Workplane() + .sketch() + .push([ + (r, r * math.tan(th)) + ]) + .circle(self.angle_joint_flange_radius) + .reset() + .regularPolygon(self.side_width_inner, self.n_side, mode="i") + .finalize() + .extrude(self.angle_joint_flange_thickness) + .translate((0, 0, -self.angle_joint_flange_thickness/2)) + ) + ri = self.stator_bind_radius + h = self.angle_joint_flange_thickness + # drill hole + cyl = Cq.Solid.makeCylinder( + radius=self.rotor_bind_bolt_diam/2, + height=h, + pnt=(ri * math.cos(th), ri * math.sin(th), -h/2), + ) + return flange - cyl + @target(name="angle-joint-chamber-back") def angle_joint_chamber_back(self) -> Cq.Workplane: slot = ( @@ -996,34 +1024,10 @@ class Onbashira(Model): result.tagAbsolute(f"holeRSO{i}", locrot * Cq.Location(dr, -x, -py), direction="+X") # Generate the flange geometry + flange = self.angle_joint_flange() + result = result + self.angle_joint_flange() th = math.pi / self.n_side - flange = ( - Cq.Workplane() - .sketch() - .regularPolygon(self.side_width_inner, self.n_side) - .regularPolygon(self.side_width_inner - self.angle_joint_flange_extension, self.n_side, mode="s") - .finalize() - .extrude(self.angle_joint_gap) - .translate((0, 0, -self.angle_joint_gap/2)) - ) - flange = flange * intersector ri = self.stator_bind_radius - h = self.angle_joint_gap - # Drill holes for connectors - cyl = Cq.Solid.makeCylinder( - radius=self.rotor_bind_bolt_diam/2, - height=h, - pnt=(0, 0, -h/2), - ) - side_pos = Cq.Location(ri * math.cos(th), self.angle_joint_extra_hole_offset, 0) - side_pos2 = Cq.Location.rot2d(360/self.n_side) * side_pos.flip_y() - result = ( - result - + flange - - cyl.moved(ri * math.cos(th), ri * math.sin(th), 0) - - cyl.moved(side_pos.toTuple()) - - cyl.moved(side_pos2.toTuple()) - ) result.tagAbsolute("holeStatorL", (ri * math.cos(th), ri * math.sin(th), h/2), direction="+Z") result.tagAbsolute("holeStatorR", (ri * math.cos(th), ri * math.sin(th), -h/2), direction="-Z") return result @@ -1146,33 +1150,10 @@ class Onbashira(Model): result.tagAbsolute(f"holeRSM{i}", locrot * Cq.Location(dr0, -x, -py), direction="-X") # Generate the flange geometry + flange = self.angle_joint_flange() + result = result + self.angle_joint_flange() th = math.pi / self.n_side - flange = ( - Cq.Workplane() - .sketch() - .regularPolygon(self.side_width_inner, self.n_side) - .regularPolygon(self.side_width_inner - self.angle_joint_flange_extension, self.n_side, mode="s") - .finalize() - .extrude(self.angle_joint_gap) - .translate((0, 0, -self.angle_joint_gap/2)) - ) - flange = flange * intersector ri = self.stator_bind_radius - h = self.angle_joint_gap - cyl = Cq.Solid.makeCylinder( - radius=self.rotor_bind_bolt_diam/2, - height=h, - pnt=(0, 0, -h/2), - ) - side_pos = Cq.Location(ri * math.cos(th), self.angle_joint_extra_hole_offset, 0) - side_pos2 = Cq.Location.rot2d(360/self.n_side) * side_pos.flip_y() - result = ( - result - + flange - - cyl.moved(ri * math.cos(th), ri * math.sin(th), 0) - - cyl.moved(side_pos.toTuple()) - - cyl.moved(side_pos2.toTuple()) - ) result.tagAbsolute("holeStatorL", (ri * math.cos(th), ri * math.sin(th), h/2), direction="+Z") result.tagAbsolute("holeStatorR", (ri * math.cos(th), ri * math.sin(th), -h/2), direction="-Z") return result @@ -1194,7 +1175,9 @@ class Onbashira(Model): def handle(self) -> Cq.Workplane: w = self.side_width + self.angle_joint_extra_width base = ( - Cq.Workplane() + Cq.Workplane( + origin=(0, 0, -self.handle_base_height) + ) .box( length=w, width=self.angle_joint_depth, @@ -1216,16 +1199,40 @@ class Onbashira(Model): depth=None, ) ) - handle = ( - Cq.Workplane(origin=(0, 0, self.handle_height)) - .box( - length=self.handle_length, - width=self.handle_thickness, - height=self.handle_thickness, - ) + dx = self.handle_length / 2 - self.handle_thickness / 2 + assert self.handle_length < w + z = self.handle_height - self.handle_thickness / 2 + handle = Cq.Solid.makeCylinder( + radius=self.handle_thickness/2, + height=dx * 2, + pnt=(-dx, 0, z), + dir=(1, 0, 0), ) - return base + handle + pillar = Cq.Solid.makeCylinder( + radius=self.handle_thickness/2, + height=z, + ) + joint = Cq.Solid.makeSphere(radius=self.handle_thickness/2) + result = ( + base + + handle + + pillar.moved(dx, 0, 0) + + pillar.moved(-dx, 0, 0) + + joint.moved(dx, 0, z) + + joint.moved(-dx, 0, z) + ) + t = self.handle_base_height + for i, (x, y) in enumerate(self.angle_joint_bolt_position): + result.tagAbsolute(f"holeLPO{i}", (+x, y, 0), direction="+Z") + result.tagAbsolute(f"holeLSO{i}", (-x, y, 0), direction="+Z") + result.tagAbsolute(f"holeLPI{i}", (+x, y, -t), direction="-Z") + result.tagAbsolute(f"holeLSI{i}", (-x, y, -t), direction="-Z") + result.tagAbsolute(f"holeRPO{i}", (+x, -y, 0), direction="+Z") + result.tagAbsolute(f"holeRSO{i}", (-x, -y, 0), direction="+Z") + result.tagAbsolute(f"holeRPI{i}", (+x, -y, -t), direction="-Z") + result.tagAbsolute(f"holeRSI{i}", (-x, -y, -t), direction="-Z") + return result @assembly() def assembly(self) -> Cq.Assembly: a = Cq.Assembly() @@ -1269,8 +1276,26 @@ class Onbashira(Model): material=self.material_side, role=Role.STRUCTURE | Role.DECORATION, ) - .add(self.assembly_barrel(), name="barrel") + .addS( + self.handle(), + name="handle", + material=self.material_brace, + role=Role.STRUCTURE, + ) + #.add(self.assembly_barrel(), name="barrel") ) + # Add handle + for ih, (x, y) in enumerate(self.angle_joint_bolt_position): + a = a.constrain( + f"handle?holeLPI{ih}", + f"ring2/side0?holeLPO{ih}", + "Plane", + ) + a = a.constrain( + f"handle?holeRPI{ih}", + f"ring2/side0?holeRPO{ih}", + "Plane", + ) for i in range(self.n_side): j = (i + 1) % self.n_side for ih in range(len(self.angle_joint_bolt_position)): @@ -1290,11 +1315,11 @@ class Onbashira(Model): "Plane", ) - a = a.constrain( - f"barrel/stator2?holeB{i}", - f"ring1/side{i}?holeStatorR", - "Plane", - ) + #a = a.constrain( + # f"barrel/stator2?holeB{i}", + # f"ring1/side{i}?holeStatorR", + # "Plane", + #) # Generate bolts for the chamber back name_bolt =f"chamber_back{i}boltFPI{ih}"