fix(com): hatch islands on a live seat — typed edges become temporary entities

hatch_add_boundary was refused on COM (hatch_edge_paths), so a transverse
section of any hollow part — a bushing, a flange bore — could not be drawn in
AutoCAD at all: draw_prims asked the capability map and refused up front.

ActiveX takes a loop as whole objects, which is not the same as "cannot take a
typed edge": each edge now becomes a real temporary LINE, true ARC or ELLIPSE
in the hatch's own space, appended with AppendInnerLoop, evaluated and
deleted. A loop that is only chained lines becomes one closed polyline — one
COM call instead of 180 for a flattened bore. The edge list is validated in
full first with the headless engine's messages; a loop AutoCAD refuses is
taken back out with its temporaries.

Measured on AutoCAD 2026 (25.1s), in scratch documents closed unsaved:
- a two-arc island leaves exactly 10000 - 100*pi (9685.8407) of a 100 x 100 hatch;
- the OD40/ID20 sleeve's transverse section B-B, drawn through the view engine
  and draw_prims, hatches 942.2864 mm2 — the engine's declared 180-gon;
- an open chain is refused (E_FAIL) and the entity count is unchanged.

hatch_edge_paths is now supported on both engines.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FKFStjEFzpGyLq5bMpWxTd
This commit is contained in:
Umut CAN
2026-09-23 13:51:35 +03:00
co-authored by Claude Opus 5.5
parent e6f685643d
commit 2bba18d0f7
6 changed files with 368 additions and 18 deletions
+6 -4
View File
@@ -216,10 +216,12 @@ async def _ensure_layers(backend, names) -> tuple[str, ...]:
def _refuse_islands_without_edge_paths(backend, prims) -> None:
"""Refuse a hatch with islands on an engine that cannot attach them - before drawing.
Islands go through `hatch_add_boundary`, which the live engine refuses
(capability ``hatch_edge_paths``: ActiveX appends loops as objects, not
typed edges). Finding that out at the hatch would leave the rest of the
view already drawn; asking the capability map first leaves nothing behind.
Islands go through `hatch_add_boundary` (capability ``hatch_edge_paths``).
Both shipped engines support it - the live one turns each typed edge into a
temporary LINE/ARC/ELLIPSE and appends it with ``AppendInnerLoop`` - but a
backend that declares it unsupported must say so before anything is drawn:
finding out at the hatch would leave the rest of the view already on the
sheet, while asking the capability map first leaves nothing behind.
"""
if not any(isinstance(p, HatchArea) and len(p.loops) > 1 for p in prims):
return