Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions src/draftwright/_geometry.py
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,18 @@ def _radial_axis_in_view(axis: str, view: str) -> str:
raise ValueError(f"no radial axis for shaft axis {axis!r} in view {view!r}") from e


def _cylindrical_finish_site(reference):
"""Preferred visible site for one external orthographic cylinder finish."""
axis = reference.principal_axis.lower()
if reference.sense != "external" or axis not in _EDGE_ON:
return None
view = _EDGE_ON[axis]
radial = _radial_axis_in_view(axis, view)
site = list(reference.midpoint)
site["xyz".index(radial)] += reference.radius
return (tuple(site), view, "above" if radial == "z" else "right")


def _canonical_profile_site(site, centre, axis: str, view: str) -> tuple[float, float, float]:
"""Rotate a turned surface *site* about its shaft onto the selected profile plane.

Expand Down
39 changes: 39 additions & 0 deletions src/draftwright/annotations/_gdt.py
Original file line number Diff line number Diff line change
Expand Up @@ -287,9 +287,48 @@ def _gdt_visual_tolerance(glyph, draft, zone: str, *, modifier: bool = False) ->
return ""


def _gdt_visual_finish(glyph, draft, value: str) -> str:
"""Trust a finish value only when its glyph faces spell that value."""
try:
expected = Text(
value,
font_size=draft.font_size,
font=getattr(draft, "font", "Arial"),
font_path=getattr(draft, "font_path", DEFAULT_FONT_PATH),
align=(Align.MIN, Align.MIN),
mode=Mode.PRIVATE,
)
x0, y0, x1, y1 = glyph.label_bbox
box = expected.bounding_box()
expected = expected.moved(Location(Vector(x0 - box.min.X, y0 - box.min.Y, 0)))
tolerance = max(1e-3, draft.font_size * 1e-3)
faces = [
face
for face in glyph.faces()
if (face_box := face.bounding_box()).min.X >= x0 - tolerance
and face_box.max.X <= x1 + tolerance
and face_box.min.Y >= y0 - tolerance
and face_box.max.Y <= y1 + tolerance
]
if not faces:
return ""
actual = Sketch(children=faces)
area_tolerance = max(1e-8, draft.font_size**2 * 1e-8)
if (
_cut_area(expected.cut(actual)) <= area_tolerance
and _cut_area(actual.cut(expected)) <= area_tolerance
):
return value
except Exception:
return ""
return ""


def _attach_gdt_text_evidence(leader, glyph, item, draft) -> None:
"""Keep the placed glyph's value beside PDF text for independent PMI lint."""
leader.pdf_text_relative_specs = _gdt_pdf_text_specs(glyph, item, draft)
if item.kind == "finish":
leader.gdt_visual_finish = _gdt_visual_finish(glyph, draft, item.ra)
if item.kind == "control_frame":
zone = _gdt_visual_zone(glyph, draft)
leader.gdt_visual_tolerance = _gdt_visual_tolerance(
Expand Down
1 change: 1 addition & 0 deletions src/draftwright/linting/orchestration.py
Original file line number Diff line number Diff line change
Expand Up @@ -629,6 +629,7 @@ def _lint_pmi(ctx: LintContext) -> list:
ctx.analysis.pmi_mode,
decorations=getattr(ctx.model, "decorations", {}),
report=ctx.analysis.pmi_report,
drawing=ctx.drawing,
overridden_general_tolerance=(
ctx.analysis.tolerance is not None and ctx.build.general_tolerance_source is None
),
Expand Down
Loading
Loading