3248bfbfea50c5a9fe2c27db784fcc029b6796d6
3
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
3ef316d520 |
feat(refs): xrefs, raster underlays, data extract and real DWG output
SECTION 24 completes at eleven tools with xref_attach, xref_manage,
image_attach, data_extract and drawing_export_dwg, on the four contract members
that genuinely differ per engine -- backends/contracts/refs.py. Everything else
in the sheet track composes the generic members and is written once.
The ActiveX members were read off the AutoCAD 2026 seat's own type library
(C:\Program Files\Common Files\Autodesk Shared\acax25enu.tlb, "AutoCAD 2025
Type Library" 1.0, the library the running 25.x seat registers) before a line of
the COM path was written, and the measurement is in the code beside the calls:
IAcadModelSpace.AttachExternalReference(PathName, Name, InsertionPoint,
Xscale, Yscale, Zscale, Rotation, bOverlay, Password)
IAcadModelSpace.AddRaster(imageFileName, InsertionPoint, ScaleFactor,
RotationAngle)
IAcadBlock: IsXRef (get), Path (get AND put -- so the repath is an assignment,
not a method), Reload(), Unload(), Bind(bPrefixName), Detach(),
XRefDatabase (get)
IAcadDocument.SaveAs(FullFileName, SaveAsType, vSecurityParams)
AcSaveAsType: ac2000_dwg=12 ac2004_dwg=24 ac2007_dwg=36 ac2010_dwg=48
ac2013_dwg=60 ac2018_dwg=64 (=acNative)
The running seat itself was not answering COM while this landed (its window was
Not Responding and GetActiveObject never returned), so the type library -- which
is the same seat's declared surface and reads without a call into the process --
is what the members are measured from; no document of the operator's was opened
or touched. This repository has been bitten four times by a fake that invented a
member, so the COM fakes in the tests model those names and nothing else.
ActiveX angles are radians, so the degree-to-radian conversion happens at that
boundary and nowhere else.
Headlessly, ezdxf.xref.attach carries the attachment (measured on ezdxf 1.4.4:
block flags 20 for an attachment and 24 for an overlay, so "is this an xref" is
flags & (BLK_XREF | BLK_XREF_OVERLAY) -- masking BLK_XREF alone misses every
overlay), add_image_def + add_image the raster, with Pillow reading the pixel
size so the placed image keeps the file's aspect.
Three capability keys, declared in both maps:
dwg_write -- measured absent here (odafc.is_installed() is False), so the
ezdxf entry is a runtime re-evaluation like viewport_render's
matplotlib check rather than a hardcoded False: installing the
ODA File Converter starts the call working with no edit to the
map. The refusal names the install route and drawing_export_dxf.
xref_live -- reload and bind need a live seat's xref manager and are refused
headlessly; list, detach and path are headless and are not
behind the key.
xlsx_write -- openpyxl is optional and absent here; CSV is always available,
so the refusal never blocks the deliverable and says so.
Two numbers the plan predicted wrongly are corrected to what the registry
actually does. `block` outranks `drawing` in _GROUP_TAG_PRIORITY, so the two
xref tools file under `blocks` (9 -> 11) beside block_insert -- which is where
an xref belongs, being a block definition that lives in another file -- and
`drawing` moves 11 -> 12, not 11 -> 14. And `data_extract` must not say "parts
list" in its own text: that is the golden discovery query for
entity_create_table, and a file writer outranking the tool that draws the thing
is a regression the tuning bar catches. It is described by its destination --
a file -- instead.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FKFStjEFzpGyLq5bMpWxTd
|
||
|
|
499b642fbd |
feat(sheet): revisions, the ISO 7573 parts list and ISO 6433 balloons
SECTION 24 grows to six tools: revision_add, bom_extract, bom_table,
balloon_add.
bom_extract reads. It walks the INSERTs through the generic members already in
the contract -- entity_list, block_get_attributes, entity_get_xdata -- and
returns parts-list rows from the ACADMCP_MECH std_part payload, falling back to
the block's own ATTRIBs and reporting which of the two each row came from. A
block with neither is skipped rather than guessed at, and the tool never writes
to the drawing.
bom_table draws the rows as a real TABLE, 180 mm wide (ISO 7573: the item list
is as wide as the title block), growing upwards from directly above it with the
heading row against the block and item 1 the row above -- which is what ISO 7573
asks for on a drawing. A TABLE is drawn downwards from its insertion point, so
the upward list is inserted a table height above its anchor with the heading as
the last row; one table_layout feeds both the real TABLE and the pure
table_prims, so the two renderings cannot disagree.
balloon_add draws the ISO 6433 reference -- numeral, leader, dot on the item --
and writes the balloon payload naming its targets. A rerun over the same
targets renumbers that balloon instead of drawing a second one, and an item
number already used for different targets is refused by name with the other
balloon's handle.
revision_add appends a row to the revision block, is idempotent per revision
code (a repeat draws nothing at all), and optionally clouds the changed regions
and tags them with the triangle. Clouds are refused up front, carrying
capability "revcloud", on an engine that has no revcloud member -- the COM
backend -- rather than leaving half a revision behind.
Declared: ISO 7200 does not standardise the revision block's geometry and
ISO 7573 does not fix the item list's column widths or row height, so both
reuse this repository's 180 mm / 7 mm ruling and say so in their SOURCE
docstrings. ISO 6433's "numeral at least twice the dimension character height"
is met by the numeral being 1.4x the balloon radius: the 4 mm default clears
2.5 mm dimension text, and balloon_add's docstring tells a sheet dimensioned at
3.5 mm to pass radius=5.0.
Three corrections to what the plan wrote, each measured rather than assumed:
* extract_records read `block_get_attributes(...)["attributes"]`. Both engines
return the flat {tag: value} mapping itself (ezdxf_backend.py:6687 builds it
from `ent.attribs`, com_backend.py:5703 from `ref.GetAttributes()` as
{TagString: TextString}), so every attribute fallback would have been
silently empty -- measured headlessly, where a PLATE insert carrying only a
DESIGNATION ATTRIB extracted to nothing.
* draw_bom_table now reports `entity_type` / `representation` /
`child_handles`. `entity_create_table` returns EntityInfo(type="TABLE") whose
handle is the first CHILD of a composite on the headless engine, so reading
that handle back gives a rule LINE, not an ACAD_TABLE -- the contract
tests/test_table_leader.py already pins. A caller that means to edit the
table afterwards has to be told which of the two it got.
* add_revision reports one `tags` entry per tag asked for ({at, handles}), not
one per entity: a tag is two primitives, so a flat handle list claimed twice
as many tags as the caller requested.
Discovery: `bom_extract` / `bom_table` / `balloon_add` each entered the index
heavy with "parts"/"list" tokens and took top-1 for the bare query "parts list"
away from `entity_create_table` (a BM25 tie broken alphabetically). Narrowed on
my side only -- the reader speaks of the bill of materials, the drawer names a
table, the balloon names an item -- never by touching the golden case.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FKFStjEFzpGyLq5bMpWxTd
|
||
|
|
56e6ff7206 |
feat(sheet): ISO 5457 frames and ISO 7200 title blocks for A4-A0
SECTION 24 opens with sheet_frame and titleblock_apply. engineering/sheet/frames.py transcribes ISO 216's trimmed sizes, ISO 5457's 20 mm filing margin and 10 mm edges, the grid reference system (an even number of divisions per side, that side of the frame over 50 mm; letters from the top, numbers from the left), the centring marks (trimmed edge to 5 mm inside the frame) and the 10 x 5 mm corner trimming marks. Every one of those numbers is pinned by a test against the clause it comes from, because a wrong margin is visible on every drawing this server makes. engineering/sheet/titleblock.py draws the ISO 7200 block -- 180 mm wide, which is exactly the drawing-space width of a portrait A4, which is why one block fits every size -- and carries the ISO 128-30 projection-angle symbol. Which symbol is which is derived rather than remembered: first-angle projection puts the view seen from the left on the right, and the view of the cone from its small end is the small circle inside the large one, so first angle draws the cone left and the circles right. The old A3 module folds in. apply_iso_a3_titleblock now forwards to apply_titleblock(size="A3", projection=None, zones=False, marks=False), which is the geometry it always drew, and tests/test_engineering_titleblock.py passes unchanged -- that is the regression gate for the fold. No new ActiveX member is called: both tools reach the drawing only through contract members the A3 title block has used on both engines since v1.0 (entity_create_polyline / _line / _circle / _text, layout_list, layout_set_current), so there was nothing to probe live. Declared, not glossed: the zone divisions drawn here are equal, so ISO 5457's allowance for shorter corner fields is not implemented; the division counts, which are what a zone reference quotes, are the standard's. ISO 7200's full optional-field list is not transcribed, only the fields this block has a cell for. Coverage is A4-A0; an unknown size is refused by name with the five it has. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FKFStjEFzpGyLq5bMpWxTd |