sheet_bend 的一个文件
This commit is contained in:
@@ -355,6 +355,111 @@ class ThreadSpec:
|
||||
)
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class BendLeg:
|
||||
"""One straight wing of a bent sheet-metal chain (runtime-neutral).
|
||||
|
||||
``leg_mm`` is the straight mid-plane distance from the previous fold vertex
|
||||
to the fold vertex leaving this wing (the unfolded chord length between the
|
||||
two surrounding fold vertices). When the wing has a following wing,
|
||||
``bend_angle_deg`` is the required *interior* angle between the two wings
|
||||
(0 < angle < 180, 90 = a right-angle bend), ``inner_radius_mm`` the inner
|
||||
bend-surface fillet radius (>= 0; the outer radius is always
|
||||
``inner_radius_mm + thickness_mm``) and ``side`` the fold direction
|
||||
(+1 / -1). A trailing wing carries no fold; stray fold fields on the last
|
||||
wing are ignored for tolerance.
|
||||
"""
|
||||
|
||||
leg_mm: float
|
||||
bend_angle_deg: float | None = None
|
||||
inner_radius_mm: float = 0.0
|
||||
side: int = 1
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class BendSpec:
|
||||
"""Runtime-neutral definition of a sheet-metal bend (``bend_add``).
|
||||
|
||||
The part is described by its mid-plane centreline: ``chain`` lists the
|
||||
straight wings joined by equal-thickness bend corners. ``thickness_mm``
|
||||
and ``width_mm`` are the sheet thickness and the full length along the fold
|
||||
(width) axis. ``frame.origin_mm`` anchors the start of the first wing's
|
||||
mid-plane path, ``frame.x_dir`` is the fold/width axis and
|
||||
``frame.normal`` is the mid-plane normal of the first wing; the first wing
|
||||
extends along ``normal x x_dir``.
|
||||
|
||||
The spec deliberately contains no OCC planes or shapes. The adapter turns
|
||||
this definition into a bent solid keeping source-contract parsing separate
|
||||
from B-rep work (same pattern as :class:`ThreadSpec`).
|
||||
"""
|
||||
|
||||
thickness_mm: float
|
||||
width_mm: float
|
||||
frame: PlaneSpec
|
||||
chain: tuple[BendLeg, ...]
|
||||
|
||||
@classmethod
|
||||
def from_feature(cls, params: dict[str, Any]) -> "BendSpec":
|
||||
try:
|
||||
thickness = float(params.get("thickness_mm") or 0.0)
|
||||
width = float(params.get("width_mm") or 0.0)
|
||||
except (TypeError, ValueError) as error:
|
||||
raise ValueError("bend thickness/width must be numeric") from error
|
||||
if thickness <= 0 or width <= 0:
|
||||
raise ValueError("bend requires positive thickness_mm and width_mm in millimetres")
|
||||
raw_chain = params.get("chain")
|
||||
if not isinstance(raw_chain, (list, tuple)) or not raw_chain:
|
||||
raise ValueError("bend requires a non-empty chain of wing segments")
|
||||
chain: list[BendLeg] = []
|
||||
for index, raw_leg in enumerate(raw_chain):
|
||||
if not isinstance(raw_leg, dict):
|
||||
raise ValueError(f"bend chain[{index}] must be an object with leg_mm")
|
||||
try:
|
||||
leg = float(raw_leg.get("leg_mm") or 0.0)
|
||||
except (TypeError, ValueError) as error:
|
||||
raise ValueError(f"bend chain[{index}].leg_mm must be numeric") from error
|
||||
if leg <= 0:
|
||||
raise ValueError(f"bend chain[{index}].leg_mm must be positive")
|
||||
bend_angle: float | None = None
|
||||
if index < len(raw_chain) - 1:
|
||||
raw_angle = raw_leg.get("bend_angle_deg")
|
||||
if raw_angle is None:
|
||||
raise ValueError(
|
||||
f"bend chain[{index}] needs bend_angle_deg for the fold towards the next wing"
|
||||
)
|
||||
try:
|
||||
bend_angle = float(raw_angle)
|
||||
except (TypeError, ValueError) as error:
|
||||
raise ValueError(f"bend chain[{index}].bend_angle_deg must be numeric") from error
|
||||
if not 0 < bend_angle < 180:
|
||||
raise ValueError("bend interior angle must be between 0 and 180 degrees")
|
||||
radius = float(raw_leg.get("inner_radius_mm") or 0.0)
|
||||
raw_side = raw_leg.get("side")
|
||||
side = 1 if raw_side is None else int(raw_side)
|
||||
if radius < 0:
|
||||
raise ValueError(f"bend chain[{index}].inner_radius_mm must be non-negative")
|
||||
if side not in (1, -1):
|
||||
raise ValueError(f"bend chain[{index}].side must be +1 or -1")
|
||||
chain.append(BendLeg(
|
||||
leg_mm=leg,
|
||||
bend_angle_deg=bend_angle,
|
||||
inner_radius_mm=radius,
|
||||
side=side,
|
||||
))
|
||||
raw_frame = params.get("frame")
|
||||
if isinstance(raw_frame, dict):
|
||||
frame = PlaneSpec.from_mapping(raw_frame)
|
||||
else:
|
||||
# frame 缺省:首翼沿世界 +X 延伸、厚度沿 +Y、折痕沿 +Z(贴 XY 平面)。
|
||||
frame = PlaneSpec(
|
||||
origin_mm=(0.0, 0.0, 0.0),
|
||||
x_dir=(0.0, 0.0, 1.0),
|
||||
y_dir=(1.0, 0.0, 0.0),
|
||||
normal=(0.0, 1.0, 0.0),
|
||||
)
|
||||
return cls(thickness_mm=thickness, width_mm=width, frame=frame, chain=tuple(chain))
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class RuntimeDiagnostic:
|
||||
code: str
|
||||
|
||||
Reference in New Issue
Block a user