Skip to content

Write the ACIS payload of 3DSOLID, REGION and BODY to DXF and DWG#1150

Open
ilCosmico wants to merge 15 commits into
DomCR:masterfrom
ilCosmico:acis-write
Open

Write the ACIS payload of 3DSOLID, REGION and BODY to DXF and DWG#1150
ilCosmico wants to merge 15 commits into
DomCR:masterfrom
ilCosmico:acis-write

Conversation

@ilCosmico

Copy link
Copy Markdown
Contributor

This is the write side of #1139 (reading the ACIS payload of 3DSOLID, REGION and BODY), now merged. The DWG and DXF writers used to skip those entities; they now write the ACIS payload back.

The payload is the same SAT or SAB byte stream regardless of the file type. Only the container changes with the version, so the writer puts the bytes where each version expects them:

  • Pre-2013 DXF: SAT text in group codes 1 and 3, with the character swap those codes use.
  • Pre-2013 DWG: the payload in the entity stream, SAT text in the version 1 block or the raw stream in the version 2 block.
  • 2013 and later DXF: the binary SAB in the ACDSDATA section.
  • 2013 and later DWG: the binary SAB in the AcDs data section, which was not written before. The segment directory carries the owner handle, so each payload maps back to its entity, and the payload area is anchored from the directory size so the offsets hold for any record count.

The R2013 and later modeler geometry entity read path is aligned with the same layout (no ACIS empty bit and no silhouette block before the wireframe), so the reader and writer agree.

Tests cover the SAT text codec, the DXF ACDSDATA section, and the DXF SAT round-trip, next to the existing writer tests.

One dependency worth noting: R2013 and later DWG files also need the small viewport reference-type fix in #1149 to open cleanly in AutoCAD.

ilCosmico added 15 commits July 15, 2026 15:10
…try entity layout

The section content is byte-identical to the reference produced by the
reference writer for the same payloads. A residual issue in the section
framing (page count / section id) still prevents third party readers from
attaching the payloads; the managed round-trip reads it back correctly.
…entities

After the ACIS payload the entity carries a wireframe-data-present flag
and, from R2007 on, a trailing int. Without them the readers pick up
garbage bits past the payload and run off the object data.
The 350 group is mandatory since the 2007 format: when it misses,
AutoCAD discards the whole DXF as invalid input.
The CAD writers emit SAT text as version 1 blocks at every release, with
the leading bit set, and reserve version 2 for the raw binary payload
with the bit clear. Writing text through version 2 produces entities the
modeler rejects.
The writer left every section id at 0 and skipped the empty section that
the format places first in the descriptor map. Plain drawings open anyway
since applications resolve sections by name, but the AcDs data store keys
on the section id, so its records were dropped as out of range. Number the
sections from 1 and prepend the empty section, matching the reference.
The reference writers set the has-revision-guid flag to 0 and write no
revision fields. Emitting the flag as 1 with placeholder fields makes the
Autodesk modeler reject the entity as out of range, even though the
managed reader skips the fields and round-trips either way.
Decoded from the raw bits of the reference entities: the R2013+ stream
has no ACIS empty bit, it opens with the wireframe block, then the
trailing int, the revision guid in its native layout and the end marker.
The extra leading bit shifted every following field, so the CAD readers
picked up garbage values and dropped the entities as out of range.
Decoded from an Autodesk-written R2013 file of the same scene: the block
is four bits (acis empty, no wireframe, acis empty again, no revision
guid), not the wireframe-plus-guid layout written before. The stray
leading bit and the random revision guid made the modeler reject the
solids.
The last header field of the _data_ segment locates the payload area:
its value times 16 is the offset from the segment header to the first
payload. The writer hardcoded the value captured from a nine-record
reference file, so the CAD readers anchored the payloads at the wrong
offset for any other record count and every ACIS payload came back as
garbage. Compute the field from the directory size instead; the value
now matches the reference files at every record count.
@ilCosmico

Copy link
Copy Markdown
Contributor Author

Rebased on current master (which now includes #1149) and added one commit. Following the discussion in #1152, I audited the AcDs writer field by field against chapter 24 of the .dwg file specification, and that audit found one real defect: in the search segment, the per-handle index stored the record's directory position instead of its rank in the sorted handle order. The two coincide when the directory is already sorted by handle, which is why every file opened fine so far; a file saved by AutoCAD with out-of-order handles shows the correct behavior. The new commit fixes it and adds regression tests built from that file.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant