Skip to content

fix: add AEC_MODI and AEC_SYMB_SECTION as ProxyEntity in readUnlisted… - #1148

Open
WallanceLee wants to merge 2 commits into
DomCR:masterfrom
WallanceLee:fix/aec-proxy-entity-support
Open

WallanceLee wants to merge 2 commits into
DomCR:masterfrom
WallanceLee:fix/aec-proxy-entity-support

Conversation

@WallanceLee

@WallanceLee WallanceLee commented Jul 10, 2026 •

Copy link
Copy Markdown

AEC custom objects (TDbSymbModi, TDbSymbSection) from BIM applications like Revit/Tianzheng are stored in DWG with proxy graphics for fallback display in AutoCAD. ACadSharp previously read these as UnknownEntity, causing their proxy graphics to be lost. Route them through readProxyEntity() so the proxy geometry data is preserved in ProxyGeometries for downstream exporters.

Description

I don't have a further knownledge about the case branches, and following is from my test data and notification handler.

Tasks done in this PR

  • Something awesome.
  • An evil bug have been defeated.
  • Code cleanup and maintenance has been done.

Related Issues / Pull Requests

  • Add the links of issues or PR related to this one.

Notes for reviewer

  • Things to consider during the review of this PR.

@WallanceLee

Copy link
Copy Markdown
Author

@DomCR Could you review this PR and let me know if you need some modification?

@DomCR

DomCR commented Jul 22, 2026

Copy link
Copy Markdown
Owner

Hi @WallanceLee,

Could you provide a file that contains those entities?

Your solution may work for these entities but given that they are part of AEC, maybe there is a more generic and better solution to include the different objects that haven't been implemented like the Wall.

Thanks!

@WallanceLee

Copy link
Copy Markdown
Author

test.dwg.zip

…Type

AEC custom objects (TDbSymbModi, TDbSymbSection) from BIM applications
like Revit/Tianzheng are stored in DWG with proxy graphics for fallback
display in AutoCAD. ACadSharp previously read these as UnknownEntity,
causing their proxy graphics to be lost. Route them through
readProxyEntity() so the proxy geometry data is preserved in
ProxyGeometries for downstream exporters.
Replace the hardcoded AEC_MODI and AEC_SYMB_SECTION cases with a generic
fallback that routes every unlisted AEC class through the proxy readers,
based on the class naming: dxf name AEC* (covers AEC_/AECS_/AECB_),
application name Aec* or cpp class name Aec*/TDb* (covers the Tianzheng/Revit
TDb family).

- objects stored in proxy format (e.g. saved without their application) are
  read as ProxyEntity or ProxyObject keeping the proxy graphics and the
  class definition, see DomCR#1148
- objects stored in their native format fall back to the unknown object
  readers, the proxy attempt runs on a copy of the readers so the object
  stream is not corrupted on failure
- extend the DxfClass notification suppression to ProxyObject

Implements the review comment of PR DomCR#1148 requesting a generic solution for
the AEC objects that are not implemented yet instead of hardcoding
AEC_MODI/AEC_SYMB_SECTION.
@WallanceLee
WallanceLee force-pushed the fix/aec-proxy-entity-support branch from 24ebd06 to 0289d75 Compare August 30, 2026 01:11
@WallanceLee

WallanceLee commented Aug 30, 2026 •

Copy link
Copy Markdown
Author

@DomCR @domeitzinger Hi, I have rewritten all with more general method. Could you give me some suggestions?

@WallanceLee

Copy link
Copy Markdown
Author

Any news?

@DomCR

DomCR commented Sep 22, 2026

Copy link
Copy Markdown
Owner

Hi @WallanceLee,

I don't think this is a good approach for the AEC and TArch entities or objects are not written as proxies, they have it's own structure.

As an example you can check the Wall AEC entity.

Related issue:

Also, the current implementation stores the Proxy Graphics when reading the different entities so it should not be a difference if they have stored graphics.

@DomCR

DomCR commented Sep 22, 2026

Copy link
Copy Markdown
Owner

If you want to procede with this branch, you can try to explore the data from each individual component and compare it to the entity in the file, and create their own reading method.

Let me know how you want to continue or if I can help you in any way.

@WallanceLee

WallanceLee commented Oct 8, 2026 •

Copy link
Copy Markdown
Author

I'd suggest closing this one, though of course that is your call — thanks for digging into it, and the AEC class-name survey in the second commit was useful.

I went through the reader path and the premise does not hold: the proxy graphics are already preserved for every entity, including the ones this PR targets.

  • readUnknownEntity calls readCommonEntityData, which reads the graphic-present flag and the graphics blob into template.ProxyGraphics.
  • CadUnknownEntityTemplate derives from CadEntityTemplate, and CadEntityTemplate turns ProxyGraphics into ProxyGeometries for every entity, so UnknownEntity already exposes the same geometry a ProxyEntity would.
  • DxfClass is also assigned to every template at the end of readUnlistedType, so the class is not lost either.

What routing through readProxyEntity adds on top is the proxy metadata — class id, version, maintenance version, original data format. Nothing in the library consumes those fields, and reading them from an object that is stored in its native format consumes bits that are not there. The fallback restores the readers only when an exception is thrown, so a read that succeeds while consuming the wrong bits would go unnoticed.

You were also right that these objects have their own structure. A proxy entity has its own object type in the file (0x1f2), so an AEC or TArch object stored natively never reaches readProxyEntity through the class table in the first place.

The part of this worth keeping is the opposite direction, and I have sent it as #1274: the retained data of a proxy was never read at all. readCommonProxyData stopped at

//Common:
//Databits X databits, however many there are to the handles
//TODO: Investigate how to read the data in proxies, it can contain data, strings and handles

and that section is the only place where the original object payload survives once it has been saved as a proxy. It has no length of its own — it runs from the end of the proxy fields up to the start of the handle section — and the reader already computes that offset while splitting the object stream, so it just needed to be kept and used.

With it read, ProxyEntity.Data and ProxyObject.Data carry the payload. Verified over 21 DWG files (1,607,215 entities in total): 0 bytes decoded before, 2358 after, with an identical entity count and a per-document fingerprint of entity types and handles in both runs.

Happy to keep working on this branch instead if you would rather go that way — just say so, and thanks again for the investigation.

This branch has not been deployed

No deployments
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.

2 participants