fix(task-23): user_select reports the picked point in WCS — GetEntity answers in the current UCS, so translate acUCS→acWorld before returning

Measured on AutoCAD 2026: under a UCS at (100,50) rotated 90 deg, a pick on a
circle at WCS (105,70) came back from IAcadUtility.GetEntity as (20,-5,0),
while Utility.GetPoint already answered in WCS. A model doing ucs_set ->
user_select -> entity_create_* at `picked` would place geometry at a silently
wrong position. The point goes through Utility.TranslateCoordinates(acUCS,
acWorld) packed as a VT_ARRAY|VT_R8 VARIANT (the plain tuple GetEntity hands
back is refused as "Invalid argument Point"). The fake Utility now models the
UCS frame and the VARIANT requirement; a new test pins the measured figures
and checks GetPoint stays untranslated. Docstrings state WCS.

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-21 21:34:26 +03:00
co-authored by Claude Opus 5
parent b83a74e969
commit 2052915f34
4 changed files with 95 additions and 5 deletions
+19 -1
View File
@@ -108,6 +108,11 @@ def _com_teardown():
pass
# AcCoordinateSystem, as Utility.TranslateCoordinates takes it (From / To).
_AC_WORLD = 0
_AC_UCS = 1
def _apoint(x: float, y: float, z: float = 0.0):
"""Create a VARIANT double-array point for AutoCAD COM."""
return win32com.client.VARIANT(
@@ -2081,11 +2086,24 @@ class ComBackend(AutoCADBackend):
if reason is None:
raise
return {"cancelled": True, "reason": reason, "handles": [], "backend": "com"}
# MEASURED (AutoCAD 2026): GetEntity's PickedPoint is in the
# *current UCS* — under a UCS at (100,50) rotated 90 deg, a pick
# on a circle at WCS (105,70) came back as (20,-5,0) — whereas
# Utility.GetPoint already answers in WCS. Every coordinate out
# of a tool is WCS, so translate acUCS → acWorld. The point must
# be a VT_ARRAY|VT_R8 VARIANT: the tuple GetEntity hands back is
# refused as "Invalid argument Point".
world = doc.Utility.TranslateCoordinates(
_apoint(picked[0], picked[1], picked[2] if len(picked) > 2 else 0.0),
_AC_UCS,
_AC_WORLD,
False,
)
return {
"cancelled": False,
"mode": "single",
"handles": [str(obj.Handle)],
"picked": [float(picked[0]), float(picked[1])],
"picked": [float(world[0]), float(world[1])],
"backend": "com",
}
doc.Utility.Prompt(f"\n{text}\n")