Files
autocad-mcp-pro/engineering/mech/__init__.py
T
Umut CANandClaude Opus 5 978c1075ad fix(task-5): cut faces on the real chord, cross sections that see features, a section with no dashed cut edge
Three defects, all of them the same mistake in three places: the cut face was
built from something other than the geometry it claims to show.

1. A prismatic cut face removed a feature by its BOUNDING BOX. `Hole.removal_box`
   is a square, so the gap punched in the cut face was the full diameter
   wherever the plane passed. On the plan's 80x50x8 plate with a Ho10 hole at
   (40, 25): a plane at y=29.9 grazes the hole (true chord 1.990) and the
   section still showed an 8 mm gap through solid metal - 560.0 mm2 hatched
   against a true 624.08, a 64 mm2 error in the hatched area AND a wrong drawn
   outline. `Slot` had the same obround-as-box. Features now answer
   `cut_spans(part, p1, unit)` with their own exact chord: `_circle_chord` for a
   hole, the union of two circles and a rotated rectangle for a slot, the
   polygon's own crossings for a pocket, and an exact slab clip of
   `removal_box` as the default. `_box_span` (the corner projection, which is
   the box's shadow and not a chord at all) is gone.

2. A transverse revolved section ignored every feature and the honesty rule
   never fired. A cross section through a DIN 6885-1 keyway came out as a plain
   hatched disc with `omitted == ()` - the commonest mechanical cross section
   there is, hatched straight over the 12x5 keyway. The face is now built by
   `_transverse_face`: its radii come from `radial_profile` (so a groove, an
   undercut, a bore or an ISO 6410 internal thread is in the face already,
   which the raw segment diameters could not report), a non-axisymmetric
   feature is asked for its own `cross_section` notch record, and one the plane
   really passes through with no such record is listed in `omitted` with its
   reason rather than hatched over. `Keyway._notch` is the one calculation the
   end view and the cut face both come out of.

3. A section drew its own cut boundary as a HIDDEN (dashed) line, because the
   longitudinal branch reused `silhouette_prims` and the silhouette draws the
   bore dashed - correct for an un-cut view, wrong for a section, where that
   line IS the hatch loop's boundary. ISO 128-50 bounds a surface lying in the
   cutting plane with a continuous wide line and ISO 128-3 leaves hidden detail
   out of a sectional view; via ROLE_LAYER['hidden'] this would also have put
   the cut boundary on the HIDDEN layer in Task 7. New `section_profile_prims`
   emits the cut outline all-continuous, and `half=True` keeps the dashed bore
   on the -Y half only, which is the half a half section does not cut.

And the claim the last commit made without earning it: the hatched area and the
drawn outline are now literally one calculation. The longitudinal loop is the
*emitted* outline flattened (`_flatten_path`), so a chamfer or fillet that
substitutes a silhouette corner is cut out of the hatch exactly where it is
drawn - a 2 mm 45 deg chamfer takes its 2 mm2 off the 1000 mm2 half face
instead of being hatched over.

Eleven new tests, every one of them red on the parent commit: the hole chord at
0/4/4.9 mm off centre, a tangent plane leaving the face whole, the 45 deg slot,
the keyway cross section against its own analytic area, the feature a cross
section cannot project, the feature the plane misses, the groove read off the
profile, the continuous cut boundary, the half section's dashed half, and the
chamfered cut face.

No new ActiveX member is called: all three fixes are pure geometry in the
backend-free `engineering/mech` package.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FKFStjEFzpGyLq5bMpWxTd
2026-09-22 22:16:47 +03:00

166 lines
2.7 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 (
CIRCLE_SEGMENTS,
PROJECTIONS,
SECTION_PLANE,
SECTION_STYLES,
VIEW_KINDS,
Band,
View,
build_view,
cut_loops,
detail_marker_prims,
detail_view,
layout_origin,
normalise_plane,
outline_prims,
radial_profile,
section_profile_prims,
section_view,
silhouette_prims,
)
__all__ = [
"Arc",
"AxialBore",
"Band",
"BendLine",
"CIRCLE_SEGMENTS",
"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",
"SECTION_PLANE",
"SECTION_STYLES",
"Segment",
"Slot",
"Text",
"Thread",
"Undercut",
"VIEW_KINDS",
"View",
"bbox",
"build_part",
"build_view",
"cut_loops",
"detail_marker_prims",
"detail_view",
"feature_from_dict",
"inner_radius_at",
"layer_for",
"layout_origin",
"mirror_about_x",
"normalise_plane",
"outer_radius_at",
"outline_bbox",
"outline_prims",
"part_length",
"part_max_diameter",
"part_to_dict",
"point_in_outline",
"points_of",
"radial_profile",
"rotate",
"scale",
"section_profile_prims",
"section_view",
"segment_bounds",
"silhouette_prims",
"translate",
"validate_part",
]