import math from typing import Optional from dataclasses import dataclass import cadquery as Cq @dataclass class TorsionSpring: """ A torsion spring with abridged geometry (since sweep is slow) """ # Outer radius radius: float = 12.0 height: float = 20.0 thickness: float = 2.0 # Angle (in degrees) between the two legs at neutral position angle_neutral: float = 90.0 tail_length: float = 25.0 right_handed: bool = False torsion_rate: Optional[float] = None @property def radius_inner(self) -> float: return self.radius - self.thickness def torque_at(self, theta: float) -> float: return self.torsion_rate * theta def generate(self, deflection: float = 0): omega = self.angle_neutral + deflection omega = -omega if self.right_handed else omega base = ( Cq.Workplane('XY') .cylinder(height=self.height, radius=self.radius, centered=(True, True, False)) ) base.faces(">Z").tag("top") base.faces("