diff --git a/nhf/touhou/houjuu_nue/wing.py b/nhf/touhou/houjuu_nue/wing.py index d05eaf5..46fd676 100644 --- a/nhf/touhou/houjuu_nue/wing.py +++ b/nhf/touhou/houjuu_nue/wing.py @@ -238,9 +238,13 @@ class WingRoot: """ panel_thickness: float = 25.4 / 16 + spacer_thickness: float = 25.4 / 8 height: float = 100.0 - shoulder_width: float = 20.0 - root_width: float = 60.0 + shoulder_width: float = 30.0 + root_width: float = 80.0 + + tip_x: float = -200.0 + tip_y: float = 160.0 def outer_spline(self) -> list[Tuple[float, float]]: """ @@ -248,34 +252,81 @@ class WingRoot: """ def profile(self) -> Cq.Sketch: - tip_x, tip_y = -100.0, 70.0 sketch = ( Cq.Sketch() .segment((-self.root_width, 0), (0, 0)) .spline([ (0, 0), - (-30.0, 50.0), - (tip_x, tip_y) + (-30.0, 80.0), + (self.tip_x, self.tip_y) ]) .segment( - (tip_x, tip_y), - (tip_x, tip_y - self.shoulder_width) + (self.tip_x, self.tip_y), + (self.tip_x, self.tip_y - self.shoulder_width) ) .segment( - (tip_x, tip_y - self.shoulder_width), + (self.tip_x, self.tip_y - self.shoulder_width), (-self.root_width, 0) ) .assemble() ) return sketch - def xy_surface(self) -> Cq.Workplane: + def spacer(self) -> Cq.Workplane: + """ + Creates a rectangular spacer. This could be cut from acrylic. - return ( - Cq.Workplane() - .placeSketch(self.profile()) - .extrude(self.panel_thickness) + There are two holes on the top of the spacer. With the holes + """ + length = self.height + width = 10.0 + h = self.spacer_thickness + result = ( + Cq.Workplane('XY') + .sketch() + .rect(length, width) + .finalize() + .extrude(h) ) + # Tag the mating surfaces to be glued + result.faces("X").workplane().tagPlane("right") + + # Tag the directrix + result.faces(">Z").tag("dir") + return result + + def surface(self, top: bool = False) -> Cq.Workplane: + tags = [ + ("shoulder", (self.tip_x, self.tip_y + 30), 0), + ("base", (-self.root_width, 0), 90), + ] + return nhf.utils.extrude_with_markers( + self.profile(), + self.panel_thickness, + tags, + reverse=not top, + ) + + def assembly(self) -> Cq.Assembly: + result = ( + Cq.Assembly() + .add(self.surface(top=True), name="bot") + .add(self.surface(top=False), name="top") + .constrain("bot@faces@>Z", "top@faces@ Tuple[Cq.Location, str]: + """ + Calculate relative location of an object in a subassembly. + + Returns the relative positions as well as the name of the top assembly. + """ + + rv = Cq.Location() + obj = self.objects[name] + name_out = name + + if obj not in self.children and obj is not self: + locs = [] + while not obj.parent is self: + locs.append(obj.loc) + obj = cast(Cq.Assembly, obj.parent) + name_out = obj.name + + rv = functools.reduce(lambda l1, l2: l2 * l1, locs) + + return (rv, name_out) +Cq.Assembly._subloc = _subloc def tagPoint(self, tag: str):