Skip to content

Add RvtIO.Scene, which turns a Revit document into an IOScene scene - #198

Merged
mahach666 merged 15 commits into
mainfrom
feat/rvtio-scene
Nov 12, 2026
Merged

mahach666 merged 15 commits into
mainfrom
feat/rvtio-scene

Conversation

@mahach666

@mahach666 mahach666 commented Nov 12, 2026 •

Copy link
Copy Markdown
Collaborator

What changes and why

Stacked on feat/public-mesh-api: the adapter maps the meshes of ElementMeshes.Extract, which that branch makes public API.

  • New project src/RvtIO.Scene (net8.0, net10.0). RvtSceneReader.Read(path), Read(document, options) and Read(document, meshes, options) turn an RVT document into an IOScene SceneDocument with one model: placed symbols as shared geometry with one instance per placement and mesh, an element's own meshes local to their lowest corner, lengths in metres, materials with name and colour. Incomplete geometry and an undecoded file are reported as diagnostics.
  • Read diagnostics: Read(path) reports a stream a reader limit cut (read-cut, error) and, per stream by the rules of the export report's issues[], members that failed to decode (failed-members, error), were rebuilt by structural recovery (recovered-members, warning) or decoded without a matching checksum (unverified-members, warning). The report's no-rows is not mapped: the element table rows have no public API. The document overloads open no file and report none of these; their docs say to read RvtReaderOptions.Diagnostics. RvtIO.Scene has InternalsVisibleTo RvtIO.Tests, as RvtIO has, for the test of this mapping.
  • Identity: SourceId is the Revit UniqueId. IfcGuid is the element's built-in IFC_GUID parameter when it is a valid GlobalId, else the export id of the UniqueId (the episode GUID with its last 32 bits XORed with the element id) in the IFC base-64 form, as Revit's IFC export derives it. Both depend on the element only; changing either is a breaking release of the adapter.
  • Properties: instance and type parameters as the text property sets revit:instance and revit:type, built-in parameters keyed revit:bip:<id>. The text is the display string of Parameter.AsValueString, written only where it is the text Revit shows. A double is written only when its unit is resolved from its measurement spec (mm, m², m³, °, A). Built-in doubles are left out for now: RvtIO guesses their unit from the parameter name (it gives TEXT_WIDTH_SCALE the unit mm). Built-in integers, element ids and values the reader only estimates (IsApproximate) are left out as well.
  • Packaging: RvtIO.Scene is packable and published on the RvtIO release tag. Its RvtIO dependency is packed as the exact version [X.Y.Z] (a target after _GetProjectReferenceVersions); IOScene is [0.1.0-preview.2, 0.2.0-0) in Directory.Packages.props, with NU5104 suppressed for that bound.
  • tools/pack-release.ps1 reads the packed nuspec and fails the release unless (a) RvtIO.Scene depends on RvtIO exactly at the release version and (b) its IOScene range has a lower bound that is not a preview. (a) guards the pin target, which hooks a private NuGet target; (b) replaces the NU5104 check.
  • Docs: docs/scene.md (usage, what the scene holds, the property text rule, diagnostics, limits), added to the toc and the API reference. docfx now evaluates the projects for net10.0 only, because the net8.0 build of RvtIO that the adapter otherwise loads fails the docs build with a System.IO.Hashing warning; the docs workflow also runs on src/RvtIO.Scene/**. Two CHANGELOG entries under [Unreleased].

Tests

Restored with IOScene 0.1.0-preview.2 from a local package folder; the version published on nuget.org has the same public API and method bodies.

  • Build (dotnet build RvtIO.slnx -c Release): 0 errors, 192 warnings, the same warning set as before the merge of feat/public-mesh-api.
  • Without the private fixtures, with feat/public-mesh-api merged: net8.0 10894 cases, 10450 passed, 444 skipped; net10.0 10898 cases, 10454 passed, 444 skipped, as recorded in docs/test-fixtures.md.
  • With the private fixture folder: net8.0 6 failed, 10767 passed, 121 skipped; net10.0 6 failed, 10771 passed, 121 skipped. The 6 failures are the bounding-box and centroid tests that fail the same way on main and on feat/public-mesh-api.
  • RvtSceneReaderTests: 26 new cases on synthetic meshes and parameters (scene validation, model fields, symbol instancing, mirrored placement, metres, own-mesh origin, names and categories, property sets and keys, approximate values, the text rule per storage type, IfcGuid from the UniqueId and the parameter override, materials, diagnostics, model key). Read diagnostics: a synthetic file with a damaged partition gives exactly one failed-members error through Read(path) (it gave none before the fix), an intact file gives none of the three codes, and the mapping is checked for order, severities and the unverified-minus-recovered rule. With RvtSceneIdentitySampleTests: 27/27 on both TFMs with the private files.
  • RvtSceneIdentitySampleTests, the golden identity test, on a private Revit 2022 sample (skipped without the private files): the model key, the element count, the UniqueId suffix of every source id, two pinned UniqueIds and the two IFC GlobalIds Revit 2022 wrote for those walls, an empty validation and no diagnostics.
  • IfcGuid checked against an IFC export written by Revit: every element Revit exported with a Tag matched.
  • Real Revit files (not committed) converted to scenes and opened in IOViewer: Validate() reported nothing.
  • tools/pack-release.ps1 under Windows PowerShell 5.1: it packed RvtIO, RvtIO.Cli and RvtIO.Scene, assertion (a) passed, and it stopped at assertion (b) as intended while IOScene is a preview. The assertion was also run on edited copies of the nuspec: a bare RvtIO version and a missing IOScene lower bound fail, a stable IOScene lower bound passes. Not run under pwsh, which the release workflow uses.
  • docfx build: not run.

Notes

  • Merge order: Add a public API for the triangle meshes of the model elements #197 (feat/public-mesh-api) first; then retarget this PR to main.
  • IOScene 0.1.0-preview.2 is on nuget.org, and CI and the docs build restore it from there and pass (re-run after its publication).
  • A release of RvtIO fails at assertion (b) until IOScene 0.1.0 is published and Directory.Packages.props moves to [0.1.0, 0.2.0-0). This is intended: no adapter built on a preview contract reaches nuget.org. The break procedure runs in one session: IOScene, then the engines, then IOViewer.
  • Follow-ups (listed under Limits in docs/scene.md): built-in doubles once their unit comes from a spec, typed values, keys for shared, project and family parameters, levels and an element tree.

RvtSceneReader maps the element meshes into one model: placed symbols as shared geometry with one instance per placement and mesh, an element's own meshes local to their lowest corner, lengths in metres, the UniqueId as the source id, names, categories, materials and the instance and type parameters as text property sets with revit: keys. Incomplete geometry and an undecoded file are reported as diagnostics. The project is not packable while the scene contract is a preview; it references IOScene with the range [0.1.0-preview.1, 0.2.0-0).
docfx evaluates every project for net10.0 only: the adapter's reference to RvtIO otherwise loads its net8.0 build, whose System.IO.Hashing support warning fails the docs build.
Parameters flagged IsApproximate are estimates of the reader (such as the fixed thermal values of a wall), not values of the file, so the scene does not carry them under revit:bip keys.
The golden test keeps the model key, the element count and the id suffix of every source id, and pins the two UniqueIds of the fixture file that tracked tests already contain.
RvtSceneReader.Read(document, meshes, options) maps meshes the caller extracted, and the tests use it, so the adapter no longer opens its internals to the test project.
… in the scene

Property text is the display string of the public parameter API, and values without an exact one are
left out. IfcGuid is the element's valid IfcGUID parameter, else the export id of its UniqueId. The
IOScene range now starts at 0.1.0-preview.2.
…UID override

The reader guesses the unit of every built-in double from its name, which gives the factor TEXT_WIDTH_SCALE the unit
mm, so a double is written only when its unit comes from its measurement spec. The IfcGuid override is the built-in
IFC_GUID parameter only, as in RvtIO's IFC export.
…diagnostics

Read(path) now adds, after read-cut and in stream order, one diagnostic per stream and kind by the rules of the
export report: failed-members (error), recovered-members and unverified-members (warnings). The element table rows
of the report's no-rows issue have no public API, so that issue is not reported. The document overloads open no
file; their docs say to read RvtReaderOptions.Diagnostics.
@mahach666
mahach666 changed the base branch from feat/public-mesh-api to main November 12, 2026 21:35
@mahach666
mahach666 merged commit c0d6157 into main Nov 12, 2026
6 of 8 checks passed
@mahach666
mahach666 deleted the feat/rvtio-scene branch November 12, 2026 21:48
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