fix(task-13): mirrored-symbol ports and COM-visible existing lines
Two review findings on pid_line_draw, both root-caused:
1. existing_pid_lines() filtered entity_list(type_filter="LWPOLYLINE") and
tested info.type == "LWPOLYLINE". A live LWPOLYLINE's ActiveX ObjectName
is AcDbPolyline (the repo's own 2026-08-06 measurement), which the COM
engine reports as POLYLINE, so on live AutoCAD every auto-built number was
seq 1, crossings always 0 and port_reuse always []. The reader now lists
without a type filter and accepts {LWPOLYLINE, POLYLINE, 2DPOLYLINE} plus
LINE — the same set the Task 14 graph reader keeps. The COM _entity_info
polyline branch matched only the DXF-flavoured "AcDbLWPolyline", so a live
LWPOLYLINE never got `points` either; it now accepts both spellings (with
the OCS normalisation), which is what makes the crossing count real there.
2. resolve_endpoint() applied only x_scale, so a mirrored INSERT
(entity_mirror writes y_scale = -1) resolved its port to a point off the
symbol and the line was drawn through the pump body. transform_port takes
an optional y_scale (default: uniform, signature unchanged) and applies the
full reflect-then-rotate transform to point, direction and radius; a
stretched symbol (|x_scale| != |y_scale|) has no circle for a radial port
and is refused with a clear ValueError instead of a silent wrong number.
Tests: mirror about both axes resolves onto the real geometry, a stretched
copy is refused, and a fake-COM AcDbPolyline probe sees the existing line
with its seq, vertices and from-ref.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FKFStjEFzpGyLq5bMpWxTd
This commit is contained in:
co-authored by
Claude Opus 5
parent
e8f1a666f8
commit
e924b5db99
+16
-6
@@ -326,6 +326,15 @@ def _com_bulge(entity, index: int) -> float:
|
||||
return 0.0
|
||||
|
||||
|
||||
# What a lightweight polyline calls itself over ActiveX. The live name is
|
||||
# ``AcDbPolyline`` (measured on AutoCAD 2026, 2026-08-06 — the member profile in
|
||||
# tests/test_com_backend.py); ``AcDbLWPolyline`` is the DXF-flavoured spelling
|
||||
# this code once matched on alone, which left every live LWPOLYLINE without
|
||||
# ``points`` because the branch never fired. Both are accepted so the vertices
|
||||
# come through whichever spelling a seat reports.
|
||||
_COM_LWPOLYLINE_NAMES = ("AcDbPolyline", "AcDbLWPolyline")
|
||||
|
||||
|
||||
def _entity_info(entity) -> EntityInfo:
|
||||
"""Convert a COM entity object to EntityInfo dataclass."""
|
||||
try:
|
||||
@@ -362,16 +371,17 @@ def _entity_info(entity) -> EntityInfo:
|
||||
# Arc length (N3) — parity with ezdxf so length_range selects ARCs.
|
||||
_sweep = (entity.EndAngle - entity.StartAngle) % (2.0 * math.pi)
|
||||
props["length"] = entity.Radius * _sweep
|
||||
elif obj_name in ("AcDbLWPolyline", "AcDb2dPolyline"):
|
||||
elif obj_name in _COM_LWPOLYLINE_NAMES or obj_name == "AcDb2dPolyline":
|
||||
coords = list(entity.Coordinates)
|
||||
pts = [[coords[i], coords[i + 1]] for i in range(0, len(coords), 2)]
|
||||
# ActiveX hands back WCS for every point property on this backend
|
||||
# *except* this one: "LightweightPolyline object: the variant is an
|
||||
# array of 2D points in OCS." Scoped to AcDbLWPolyline deliberately —
|
||||
# AcDb2dPolyline's Coordinates may be 3D triples, and changing its
|
||||
# stride on a doc reading alone, with no way to verify against live
|
||||
# AutoCAD from here, risks breaking a path that works today.
|
||||
if obj_name == "AcDbLWPolyline":
|
||||
# array of 2D points in OCS." Scoped to the lightweight polyline
|
||||
# deliberately — AcDb2dPolyline's Coordinates may be 3D triples, and
|
||||
# changing its stride on a doc reading alone, with no way to verify
|
||||
# against live AutoCAD from here, risks breaking a path that works
|
||||
# today.
|
||||
if obj_name in _COM_LWPOLYLINE_NAMES:
|
||||
try:
|
||||
normal = tuple(entity.Normal)
|
||||
if not ocs.is_wcs_frame(normal):
|
||||
|
||||
Reference in New Issue
Block a user