Skip to content

feat: read Tianzheng TDBXDATAMAP property blocks - #1275

Open
WallanceLee wants to merge 1 commit into
DomCR:masterfrom
WallanceLee:feat/tangent-datamap
Open

WallanceLee wants to merge 1 commit into
DomCR:masterfrom
WallanceLee:feat/tangent-datamap

Conversation

@WallanceLee

Copy link
Copy Markdown

Description

Tangent (TArch / 天正) stores its custom objects (TCH_* / TDb*) as ObjectARX entities.
When a drawing is saved without the application present, those objects end up as proxy entities
that retain the original object payload. That payload contains a self-describing property block
terminated by the TDBXDATAMAP_BLOCK_BEGIN_ / TDBXDATAMAP_BLOCK_END_ marker pair.

This PR adds a reader for that block, so the named properties Tianzheng stores on its objects
become available without implementing each object type.

The block is written through AcDbDwgFiler, so it uses the ordinary DWG string encoding
(BitShort character count followed by UTF-16LE) and no new bit-level logic is needed —
TchDataMap reuses IDwgStreamReader.ReadVariableText().

Real decoded example:

PIPE_SYSTEM_NAME = 消防      (fire fighting)
LINKED_DIM_TEXT  = DN25
PIPE_OUTER_DN    -> present, value written natively rather than as text
PIPE_THICK       -> present, value written natively rather than as text

Tasks done in this PR

  • Added TchDataMap to decode the Tianzheng property block.
  • Reuses the existing stream reader so the string encoding stays in one place.
  • Restores the reader position when a string cannot be decoded, so the caller can continue
    reading the enclosing object.
  • Tests against retained payloads of real proxy entities, embedded as base64 so no external
    data files are required.

Related Issues / Pull Requests

Notes for reviewer

Scope. This deliberately does not touch the object model. It decodes one self-contained
structure and hands back a dictionary, so it can be reviewed and merged independently of any
decision about how TCH_* objects should eventually be modelled.

Why not through the proxy readers (#1148). Routing these objects through readProxyEntity()
does not add anything: CadEntityTemplate already populates ProxyGeometries for every entity
template, UnknownEntity included, so the proxy graphics were never lost. On top of that the
saved proxy graphics of Tianzheng objects contain only PUSH_MATRIX / POP_MATRIX and zero
geometry primitives — I measured this over 400 entities, which matches the proxy dialog reporting
"entities with real graphics: 0".

Two properties of the format that shape the API:

  1. The block is sparse — only properties that differ from their default are written, and
    different classes carry different properties (184 of 600 sampled objects had
    PIPE_SYSTEM_NAME, 86 had the VPIPE_DIM_* group). Callers must look properties up by name.
  2. Not every value is text. The writer only formats a value into a string above a certain tag
    threshold; otherwise it writes the native type. So the block reliably tells you which
    properties exist and gives you some values. That is why Entries (the ordered raw list) is
    exposed alongside Properties, and why a name may appear with a null value.

Pairing is heuristic. Values such as DN25 are indistinguishable from names by shape, so a
naive every-other-entry pairing mis-classifies them. The implementation requires an entry to be
upper-case ASCII, and an entry containing digits is only treated as a name when it also contains
an underscore.

Test data. The payloads are the retained data of real proxy entities from a Tianzheng
plumbing drawing (TCH_PIPE, class id 575, and TCH_PIPEFITTING, class id 576). They are
embedded as base64 to keep the test self-contained.

Verification. Built and tested against current master (3.8.10) with net9.0:

Passed!  - Failed: 0, Passed: 7, Skipped: 0, Total: 7

Happy to restructure if you would prefer this to live somewhere else, or to split the
disassembly-derived notes (field order per class) into a separate document.

Tangent (TArch / Tianzheng, 天正) stores its custom objects (TCH_* / TDb*) as
ObjectARX entities. When they are saved without the application present they end
up as proxy entities carrying the original object payload, and that payload
contains a self-describing property block terminated by the
TDBXDATAMAP_BLOCK_BEGIN_ / TDBXDATAMAP_BLOCK_END_ marker pair.

The block is written through AcDbDwgFiler, so it uses the ordinary DWG string
encoding (BitShort character count followed by UTF-16LE). It is sparse: only
properties that differ from their default are present, and different classes
carry different properties. Values may be numeric text or localized text, e.g.

    PIPE_SYSTEM_NAME = 消防
    PIPE_THICK       = (present, value written natively rather than as text)

TchDataMap decodes the block and exposes both the ordered entry list and a
name/value map. It reuses IDwgStreamReader.ReadVariableText(), so the string
encoding stays in one place, and it restores the reader position when a string
cannot be decoded so the caller can carry on with the enclosing object.

The tests run against retained payloads of real proxy entities, embedded as
base64 so no external data files are needed. They cover an object with
properties, an object whose property map is empty, and a truncated payload.

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.

1 participant