Repository navigation
feat!: build the viewer on the IOScene scene model - #27
Merged
Merged
Conversation
ViewerElement.SourceId holds the element's id in its source format (a Revit UniqueId or an IFC GlobalId); the numeric Id stays the viewer key. The HTML page writes it to the META elements as "sourceId" only when set, the properties panel shows it as its own row (Source ID / ID источника) and the model tree search finds it. JSON round-trips it and leaves it out when null, so snapshots of documents without source ids are unchanged. ViewerDocument, ViewerMesh.Vertices, ViewerGeometry.Vertices and Transform3d now state that the model is in metres with Z up.
IfcViewerAdapter converts an IfcModel into a ViewerDocument in metres with Z up: one element per IFC product with the STEP id as Id, the GlobalId as SourceId, the storey as Level, and property and quantity sets as property groups. Colours come from IfcIO materials, with a fallback per IFC class, and work schedules become the TimeLiner. IfcIO bakes mapped items into world meshes, so every mesh is its own; the conversion report says so and lists elements without geometry by reason. The IfcIO version is set in EngineVersions.props (IfcIOVersion, 0.11.0, the first release with world placements); until it is published, restore needs a local feed.
README lists the engine adapters with an IfcIO example, getting started gets a From an IFC file section with the mapping and its limits, and the public API page, docfx metadata, docs workflow paths and changelog cover IOViewer.IfcIO. CONTRIBUTING states that engine adapters live here and how to build against an engine release from a local feed.
IfcIO matches products by class-name prefix, so type objects such as IfcWallType or IfcDoorStyle and door and window lining properties reached the viewer as elements without geometry. The adapter now skips them. Document that Level comes from IfcIO's storey assignment, which puts elements outside a storey and spaces in the first storey. Pack the whole solution with a prerelease of the next version for local engine builds, and note that CI, docs and release restore fail until the IfcIO version is published.
The adapter moves to the IfcIO repository as IfcIO.Scene. Remove its project, its tests, EngineVersions.props, the IfcIO package version, the two projects in the solution, the docs workflow path filters, the docfx entry and the documentation that describes it. The solution restores from nuget.org alone again.
Reference IOScene [0.1.0-preview.1, 0.2.0-0) and drop the Viewer* model classes and math types. ViewerDocument now holds a SceneDocument, the section planes and box, and the model keys hidden at start; Title reads and writes the scene title. HtmlViewerExporter gains Save, Export and ExportToString overloads that take a SceneDocument. The payload writer reads the scene and keeps the page payload of the same content: a geometry placed once is baked on the global grid as own meshes were, a geometry placed several times is written once and placed by matrices. The instance colour and the material colour carry the only opacity. Instances of lines, points or an unknown topology are skipped and counted in META "skipped", and the CLI warns about them. GLB and OBJ imports produce one model with elements, geometries, instances and materials that pass Validate(). JsonViewerExporter writes viewer JSON format 2 with the scene encoded by SceneJson.CreateOptions(). JsonViewerImporter reads viewer JSON, scene files and IOViewer 0.1/0.2 snapshots; the 0.2.0 classes stay internal in IOViewer.Legacy and one mapper turns a snapshot into a scene, with stand-in elements for meshes without one.
The viewer fixtures are regenerated as viewer JSON format 2. The survey marker of the building is now an element, as every instance of a scene belongs to one, so the element counts and the tree count one more. The test for a mesh without an element runs on a copy of the building with the marker's element removed.
The Unreleased section lists what breaks for existing users, what does not, and a table from each 0.2.0 model type and member to its scene replacement.
The changelog is checked before anything is published, the push runs before "Create release" so a refused first publication can be fixed and the job run again, and a version with a hyphen is released as a prerelease.
The 0.2.0 viewer matched a 4D task or clash id to an element, or to an ElementId group when the snapshot had no elements, and never to a mesh's own id. The mapper kept any id that named a scene element, so a reference that named nothing in 0.2.0 could now drive a mesh stand-in.
…he page The legacy mapper turns such a link name into a scene model, and the page lists every model after the first as a linked file. 0.2.0 listed only the snapshot's LinkedFiles. Pin the behaviour with a test and note it in the changelog.
JsonViewerImporter copied the whole input into memory two or three times before reading it, and so also capped it at the array size limit. It now finds the root Kind and Format with a reader that works in blocks, rewinds and deserialises from the stream. A stream that cannot seek is copied into memory once.
A clash distance is nullable: the page writes null and the clash list shows no distance for it; a 0.1/0.2 snapshot keeps the value it has. GLB base colour factors are converted from linear to sRGB. A task type the viewer does not know is a construct task in the payload and in the schedule, and an unknown projection stays perspective. The viewer fixture's third clash now reports no distance.
5 tasks done
…roperties The page parses the properties block with JSON.parse, which keeps only the last of equal member names, so of two sets with the same name on one element only the last one was shown. Sets with the same name are now one group, in the order the element first references them, and a property name that repeats in a group gets the first free suffix " (2)", " (3)". Names are compared as written, where a lone surrogate becomes U+FFFD. Elements that share an id, which Validate rejects, are one entry, as the page finds properties by element id.
…) each time A name that repeats k times in one group searched " (2)", " (3)", ... from the start for each repeat, so it took time quadratic in k: a set with 20,000 equal names took 9 s to write. The search now goes on from the last suffix given for that name; every suffix below it is taken, so the names written are the same.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What changes and why
Builds IOViewer on the scene model of the IOScene package (
IOScene[0.1.0-preview.2, 0.2.0-0), a new dependency of theIOViewerpackage) instead of its ownIOViewer.Modeltypes. Version 0.3.0-preview.1.Breaking for library users (the CHANGELOG
[Unreleased]section has a migration table from every 0.2.0 type and member to its replacement)IOScenewithScene*names,ViewerClash*included; theViewer*model classes and the math types leaveIOViewer.Model.ViewerDocumentwraps aSceneDocument(Scene) and keeps only viewer state:SectionPlanes,SectionBoxandHiddenModelKeys.Titlereads and writesScene.Title.JsonViewerExporterwrites viewer JSON format 2 ("Kind": "ioviewer"). IOViewer 0.2.0 reads such a file as an empty document with exit code 0.ioviewerarguments, GLB/OBJ to HTML, the one-package install.Library
HtmlViewerExporter.Save,ExportandExportToStringalso take aSceneDocument. The payload is the same for the same content: a geometry placed once is baked like an own mesh, a geometry placed several times is written once and placed by matrices.JsonViewerImporterreads viewer JSON, IOScene scene files and 0.1/0.2 snapshots, and reads from the stream instead of copying the whole input. The 0.2.0 classes stay internal inIOViewer.Legacy; one mapper turns a snapshot into a scene, with stand-in elements for meshes without one, and keeps only the task and clash references that 0.2.0 resolved.double?: the page writesnulland the clash list shows no distance (it showed 0). A 0.1/0.2 snapshot keeps its value.GlbViewerImporterconverts the base colour factor from linear to sRGB, so GLB colours look lighter than in 0.2.0. Alpha stays linear; channels are rounded instead of truncated.SceneElement.SourceIdand the model tree search finds it.Height (2)), so no property is lost. Elements that share an id, whichValidate()rejects, are one entry with the sets of all of them. No other member name in the page payload comes from model data.Repository
tests/fixtures/legacy-0.2. The viewer fixtures are regenerated as format 2; the building's survey marker is now an element, so its element count is one higher.release.ymlchecks the changelog section before publishing anything, pushes the NuGet packages before creating the GitHub release, and marks a version with a hyphen as a prerelease.Tests
Added or ported on this branch:
LegacyFixtureTests(each frozen 0.2.0 snapshot maps to a valid scene; stand-ins, kept references, link names), the GLB colour conversion in its linear segment and when clamped, and the C# tests, fixture generator, SyntheticModel, viewer unit tests and Playwright e2e tests ported to the scene.Run against 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):
dotnet test IOViewer.slnx -c Release: 115/115 on net8.0 and net10.0. The 6 newHtmlViewerExporterTests.Props_*cases read the properties block withUtf8JsonReaderand fail if an object repeats a member name; the first four fail before the fix. One of them writes 20,000 equal names (85 ms; 9 s with the first version of the suffix search).npm test: 144/144.npx playwright test: 109/109 (run onc38a7d3; the commit after it changes only the C# suffix search and its tests, and gives the same output).dist/viewer.jsis identical to a fresh build.dotnet docfx docfx.json --warningsAsErrors: not run.Notes
Merge order:
v0.3.0-preview.1, add a## [0.3.0-preview.1]changelog section;release.ymlnow stops before publishing without it.IOViewer.IfcIOadapter and later removes it: it moved to the IfcIO repository as IfcIO.Scene, so the net diff contains none of it.ViewerElement.SourceIdfrom an early commit is likewise superseded bySceneElement.SourceId.