Adds production-grade engineering features and tools: 2D GD&T (feature control frames + datum features) via engineering/gdt.py, ISO‑129 dimension tolerance support (engineering/tolerances.py) and an ezdxf/COM plumbing for toleranced dims, a scalar drawing score + invalidity ratio (engineering/scoring.py) wired into drawing_finalize, in-place entity editors (entity_edit_text/entity_edit_geometry), and a friendly drawing_settings facade. Includes server tool wiring, COM/ezdxf backend implementations, datum-consistency critique, many unit tests, README/CLAUDE/CHANGELOG updates, and a version bump to 1.2.0. Also corrects COM backend capability label (entities_2d).
79 lines
3.1 KiB
Python
79 lines
3.1 KiB
Python
"""ISO 129-1 dimension tolerance helpers.
|
|
|
|
A production drawing without ±/limit callouts is not manufacturable — this was
|
|
the dossier's "biggest functional gap". These helpers turn a small, explicit
|
|
tolerance spec into the ezdxf/AutoCAD dimension-variable (DIMVAR) overrides that
|
|
render tolerances, so `dimension_linear/radius/diameter` can emit toleranced
|
|
dims on both backends.
|
|
|
|
Scope (intentionally CI-testable): explicit upper/lower deviations with
|
|
symmetric / deviation / limit / basic display modes, plus a free-form text
|
|
override. The full ISO 286 fit table (H7/g6 …) is a large authored dataset and
|
|
is deferred to a follow-up; callers can already pass the resolved deviations.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
TOL_MODES = ("none", "symmetric", "deviation", "limit", "basic")
|
|
|
|
|
|
def build_dim_override(
|
|
tol_upper: float | None = None,
|
|
tol_lower: float | None = None,
|
|
tol_mode: str = "none",
|
|
text_override: str | None = None,
|
|
) -> tuple[dict, str | None]:
|
|
"""Return ``(dimvar_override, text)`` for an ezdxf ``add_*_dim`` call.
|
|
|
|
- ``tol_mode="symmetric"``: a single ± value (uses ``tol_upper``; ``±tol``).
|
|
- ``tol_mode="deviation"``: distinct upper/lower deviations (e.g. +0.02/-0.01).
|
|
- ``tol_mode="limit"``: upper/lower limits stacked instead of ± (DIMLIM).
|
|
- ``tol_mode="basic"``: theoretically-exact (boxed) dimension, no tolerance.
|
|
- ``tol_mode="none"``: no tolerance (default) — empty override.
|
|
- ``text_override``: replaces the measured text ("<>" keeps the measurement).
|
|
|
|
Raises ValueError for an unknown mode or a mode missing its required values.
|
|
"""
|
|
mode = (tol_mode or "none").strip().lower()
|
|
if mode not in TOL_MODES:
|
|
raise ValueError(
|
|
f"build_dim_override: unknown tol_mode {tol_mode!r}. Use one of {TOL_MODES}."
|
|
)
|
|
|
|
override: dict = {}
|
|
|
|
if mode == "symmetric":
|
|
if tol_upper is None:
|
|
raise ValueError("tol_mode='symmetric' requires tol_upper (the ± value).")
|
|
t = abs(float(tol_upper))
|
|
override.update({"dimtol": 1, "dimlim": 0, "dimtp": t, "dimtm": t})
|
|
elif mode == "deviation":
|
|
if tol_upper is None or tol_lower is None:
|
|
raise ValueError("tol_mode='deviation' requires tol_upper and tol_lower.")
|
|
override.update(
|
|
{
|
|
"dimtol": 1,
|
|
"dimlim": 0,
|
|
"dimtp": float(tol_upper),
|
|
"dimtm": abs(float(tol_lower)),
|
|
}
|
|
)
|
|
elif mode == "limit":
|
|
if tol_upper is None or tol_lower is None:
|
|
raise ValueError("tol_mode='limit' requires tol_upper and tol_lower.")
|
|
override.update(
|
|
{
|
|
"dimlim": 1,
|
|
"dimtol": 0,
|
|
"dimtp": float(tol_upper),
|
|
"dimtm": abs(float(tol_lower)),
|
|
}
|
|
)
|
|
elif mode == "basic":
|
|
# Theoretically-exact dimension: a box around the text. In AutoCAD a
|
|
# negative DIMGAP draws that box.
|
|
override.update({"dimgap": -1.0})
|
|
|
|
text = text_override if text_override not in (None, "") else None
|
|
return override, text
|