engineering/mech/views.py projects a part model onto a view plane and returns primitive descriptions, so a test asserts geometry rather than a screenshot. The one calculation everything comes out of for a revolved part is the radial profile: the part cut into bands of constant bore and constant (or linearly tapering) outside, with every feature's radial_edit applied. The front view is that profile walked as a path and mirrored about the axis; the section cut face of the next task is the same profile walked as a closed loop, which is what stops the outline and the hatched area ever disagreeing. Chamfers and fillets do not draw over the silhouette - they substitute their corner in it, so the overshoot the critique focus looks for cannot be produced by construction, and a corner edit that finds no corner is reported rather than dropped. A band's radii are read off the segment the band's MIDPOINT lies in and the taper is evaluated at the band's own two ends. Sampling a hair inside the band to dodge the segment-boundary ambiguity - the way the plan's draft did - writes the taper slope times that inset into every coordinate the silhouette is built from: a 30 -> 10 mm cone over 20 mm then reports 14.99999 for a radius that is exactly 15, and nothing downstream can tell that it is wrong. The end view applies a real hidden-line rule: walking the bands from the viewing end, a diameter larger than everything nearer than it is drawn hidden, a bore behind material is hidden, and the near end's own circles are visible. Looking from the left reverses it. A revolved part's top view is refused, because it repeats the front. Prismatic parts get the outline in true shape with corner fillets and chamfers substituted in, and side/top thickness rectangles - the case where a hand-drawing model reliably forgets the hidden line per through feature, which here comes out of the feature itself. The honesty rule of spec section 6 is enforced in one place: a feature that emits no primitives and edits neither the radial profile nor a corner is listed in the view's omitted tuple with its own reason. Nothing is silently dropped. layout_origin places views in first-angle positions by default (the view from the right goes to the left, the view from above goes below) and flips both for third angle. It takes one additive keyword beyond the pinned signature, child, because placing a view to the left depends on that view's own width; without it the child is assumed the parent's size and every pinned call still works. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FKFStjEFzpGyLq5bMpWxTd
148 lines
2.4 KiB
Python
148 lines
2.4 KiB
Python
"""The mechanical part model, view engine and standards tables.
|
|
|
|
Merge rule for the four track-B/G branches: the re-exports below are additive
|
|
and alphabetical — keep every side's names.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
from .features import (
|
|
FEATURE_KINDS,
|
|
AxialBore,
|
|
BendLine,
|
|
CentreHole,
|
|
Chamfer,
|
|
CornerChamfer,
|
|
CornerFillet,
|
|
CrossHole,
|
|
Feature,
|
|
Fillet,
|
|
GearTeeth,
|
|
Hole,
|
|
HoleCircle,
|
|
HolePattern,
|
|
Keyway,
|
|
ORingGroove,
|
|
Pocket,
|
|
RetainingGroove,
|
|
Slot,
|
|
Thread,
|
|
Undercut,
|
|
feature_from_dict,
|
|
mirror_about_x,
|
|
)
|
|
from .part import (
|
|
PART_KINDS,
|
|
PrismaticPart,
|
|
RevolvedPart,
|
|
Segment,
|
|
build_part,
|
|
inner_radius_at,
|
|
outer_radius_at,
|
|
outline_bbox,
|
|
part_length,
|
|
part_max_diameter,
|
|
part_to_dict,
|
|
point_in_outline,
|
|
segment_bounds,
|
|
validate_part,
|
|
)
|
|
from .primitives import (
|
|
ROLE_LAYER,
|
|
ROLES,
|
|
Arc,
|
|
Circle,
|
|
DimIntent,
|
|
HatchArea,
|
|
Line,
|
|
Poly,
|
|
Prim,
|
|
Pt,
|
|
Role,
|
|
Text,
|
|
bbox,
|
|
layer_for,
|
|
points_of,
|
|
rotate,
|
|
scale,
|
|
translate,
|
|
)
|
|
from .views import (
|
|
PROJECTIONS,
|
|
VIEW_KINDS,
|
|
Band,
|
|
View,
|
|
build_view,
|
|
layout_origin,
|
|
outline_prims,
|
|
radial_profile,
|
|
silhouette_prims,
|
|
)
|
|
|
|
__all__ = [
|
|
"Arc",
|
|
"AxialBore",
|
|
"Band",
|
|
"BendLine",
|
|
"CentreHole",
|
|
"Chamfer",
|
|
"Circle",
|
|
"CornerChamfer",
|
|
"CornerFillet",
|
|
"CrossHole",
|
|
"DimIntent",
|
|
"FEATURE_KINDS",
|
|
"Feature",
|
|
"Fillet",
|
|
"GearTeeth",
|
|
"HatchArea",
|
|
"Hole",
|
|
"HoleCircle",
|
|
"HolePattern",
|
|
"Keyway",
|
|
"Line",
|
|
"ORingGroove",
|
|
"PART_KINDS",
|
|
"PROJECTIONS",
|
|
"Pocket",
|
|
"Poly",
|
|
"Prim",
|
|
"PrismaticPart",
|
|
"Pt",
|
|
"ROLES",
|
|
"ROLE_LAYER",
|
|
"RetainingGroove",
|
|
"RevolvedPart",
|
|
"Role",
|
|
"Segment",
|
|
"Slot",
|
|
"Text",
|
|
"Thread",
|
|
"Undercut",
|
|
"VIEW_KINDS",
|
|
"View",
|
|
"bbox",
|
|
"build_part",
|
|
"build_view",
|
|
"feature_from_dict",
|
|
"inner_radius_at",
|
|
"layer_for",
|
|
"layout_origin",
|
|
"mirror_about_x",
|
|
"outer_radius_at",
|
|
"outline_bbox",
|
|
"outline_prims",
|
|
"part_length",
|
|
"part_max_diameter",
|
|
"part_to_dict",
|
|
"point_in_outline",
|
|
"points_of",
|
|
"radial_profile",
|
|
"rotate",
|
|
"scale",
|
|
"segment_bounds",
|
|
"silhouette_prims",
|
|
"translate",
|
|
"validate_part",
|
|
]
|