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:
Umut CAN
2026-09-15 23:48:35 +03:00
co-authored by Claude Opus 5
parent e8f1a666f8
commit e924b5db99
5 changed files with 243 additions and 40 deletions
+15
View File
@@ -194,6 +194,21 @@ def test_transform_port_applies_rotation_and_scale_about_the_insertion():
assert radial["direction_deg"] is None and radial["radius"] == pytest.approx(15.0)
def test_transform_port_applies_a_mirror_and_refuses_a_stretch():
port = Port("out", 0.0, 6.0, 90.0, "process")
flipped_y = transform_port(port, 100.0, 200.0, 0.0, 1.0, -1.0)
assert (flipped_y["x"], flipped_y["y"], flipped_y["direction_deg"]) == (100.0, 194.0, 270.0)
mirrored = transform_port(port, 200.0, 100.0, 180.0, 1.0, -1.0) # entity_mirror about x=150
assert (mirrored["x"], mirrored["y"]) == pytest.approx((200.0, 106.0))
assert mirrored["direction_deg"] == pytest.approx(90.0)
flipped_x = transform_port(Port("in", -4.0, 0.0, 180.0, "process"), 0.0, 0.0, 0.0, -1.0, 1.0)
assert (flipped_x["x"], flipped_x["y"], flipped_x["direction_deg"]) == (4.0, 0.0, 0.0)
radial = transform_port(Port("signal", 0.0, 0.0, None, "signal", 5.0), 0.0, 0.0, 0.0, -2.0)
assert radial["radius"] == pytest.approx(10.0)
with pytest.raises(ValueError, match="non-uniform"):
transform_port(port, 0.0, 0.0, 0.0, 2.0, 1.0)
def test_list_symbols_reports_variants_and_ports():
rows = {row["symbol"]: row for row in list_symbols()}
assert rows["instrument"]["variants"] == {