Repository navigation
fix(saved-graphics): mesh a cylinder whose saved basis is left-handed, its normal turned as on a plane (#1247) (RE-301) - #1252
Merged
Conversation
…, its normal turned as on a plane (#1247)
… size cost, and the reconnaissance addendum (#1247)
DrunkOnJava
enabled auto-merge (squash)
November 2, 2026 23:39
This was referenced Nov 2, 2026
DrunkOnJava
added a commit
that referenced
this pull request
Nov 3, 2026
… is not written as its opening alone (#1247) (RE-299) (#1249) ## Summary A door or window is no longer written as its opening alone (`IfcOpeningElement`) when its type draws geometry in no material of its own. RE-84 decides "this type only cuts its host" from a byte scan of the type's value block, and that scan misses a geometry-material map whose values are all unset or name a material whose name it did not read. The type's native `m_geomTag2MaterialId` now decides where it holds entries (RE-299). ## Motivation #1247: on a Revit 2024 project, `rvt-ifc --large-model` writes 73 `AR_DOR_` doors as `IfcOpeningElement`, the other 361 as `IfcDoor`. The RE-84 path is unchanged since v0.6.1 (the reporter's v0.6.1 could not read that file), so this is a standing misread rather than a regression. ## Changes - `src/research/native_type_materials.rs`: `geometry_maps`, which `geometry_materials` now wraps, also returns the types whose native map holds any entry. Same single native pass. - `src/research/partition_schema_mvp/materials.rs`: `refine_type_materials` drops an empty scanned list for such a type, so it reads as "materials not read" rather than "draws no geometry". Its doors and windows then also get the sizing and naming other doors and windows get, which the flag gated (RE-215 cut-loop sizes, opening-index sizes, RE-154's type name). No type material is written for it: what Revit gives such a door is not measured. One case keeps the flag: a map whose every value is −1, of a family whose own document shows none of that geometry (RE-204: every such form hidden or void, or none). No measured file has one. - `probes/examples/probe_re299_unset_map_doors.rs`, `tools/re/void_only_vs_ifc.py` (counts the probe's further columns). - `reports/element-framing/RE-299-native-map-void-only-doors.md`, an update line in RE-84, the reconnaissance addendum, `changelog.d/fixed/1247-native-map-void-only-doors.md`. ## Testing Unit tests are banned in this repository: do not add them. Show the change working end to end on real files instead. - [ ] `tools/check-local.sh`: CI. - [x] Verified end to end on real Revit files. Measure [41538550670](https://github.com/DrunkOnJava/rvt-rs/actions/runs/41538550670) (the probe on every reference model, the BIM4LCA office, the R2025 models and Autodesk's 36 samples): every door and window Revit exports as its opening alone (RE1 Architecture's CasedOpening; Snowdon Towers' 9 Door-Opening and 38 Schematic Opening Cut) has an empty native map and no saved graphics. The byte scan's all-unset signal also fires on CasedOpening and Door-Opening, so the native map is the discriminator. No other door or window in those files has a type the scan reads as mapless. - [x] Measure [41548319465](https://github.com/DrunkOnJava/rvt-rs/actions/runs/41548319465) (this change at 705c4aa, merged with `main` after #1252, against `main` at ca389bb, unfiltered, with the office, R2025, held-out models and samples): all 103 exports byte-identical (`ifc.sha256`), including the 58 sample projects and 13 held-out models, and the scorer diff is empty. Earlier gates were cancelled when the head changed: 41541177152 (first version) and 41545726999 (f832c25, before the merge). - Review (Sonnet 5.5 xhigh, automated Claude Code review): no blocking findings. Its notes are applied: the sizing and naming effect stated, the all −1 hidden-or-void case guarded, the `refine_type_materials` docs, the report's reproduce line. - [ ] The positive case is #1247's private project: the reporter was asked (with the maintainer's approval) to run `candidate/1247` at 429781b, which carries this change, and report counts. - N/A: performance (the same native pass). ## Audit-honesty checklist - [x] README / docs reflect the current state after this PR - [x] A user-visible change has its entry as a fragment under `changelog.d/` - [x] Resolved limitations: RE-84 carries the update - [x] Commit messages describe what changed and why - [x] No emojis in code, docs, or commit messages - [x] No private paths, personal email addresses, or internal jargon in committed files - [x] Reverse-engineering finding: probe, report, reconnaissance addendum ## Legal and contribution hygiene - [x] Apache-2.0 - [x] No Autodesk proprietary content - [x] No fixtures Contributor declaration (CLEANROOM.md): this finding rests on byte and record observations of public files and on Revit's own IFC exports of them; no Autodesk SDK source, disassembly or NDA material was used. ## Breaking changes None. `geometry_maps` is new under `rvt::research` (unstable).
DrunkOnJava
added a commit
that referenced
this pull request
Nov 3, 2026
…instead of keeping its fixture's box (#1247) (RE-300) (#1255) ## Summary Saved meshes leave a light fixture's light source out of its body, instead of keeping the fixture's box. The light source is saved as a `GFilter` of its own. It holds a `GImposter` (a transform and a rendering `Asset` of scalar properties, no surface) with the `Geometry`, curves and sometimes `GPolyMesh` that draw the light. Revit's export draws none of it. The traversal now leaves that filter out, as it leaves out a filter of curves (RE-300). ## Motivation #1247: a light fixture of 18,944 triangles in v0.6.1 is a 12-triangle box in v0.12.0. Reproduced on our files: Snowdon Towers electrical went from 1,420 saved meshes to 907, with 511 light fixtures kept as boxes by RE-224's partial gate. `GImposter` is the class behind 1,813 of the 3,020 partial meshes in the census (Measure 41540910235). The maintainer chose (2026-11-02) to keep boxes for meshes that do not decode whole and to close decoder gaps instead; this closes this gap without drawing anything partial. ## Changes - `src/research/native_graphics_traversal.rs`: a `GFilter` holding a `GImposter` and otherwise only leaves (`Geometry`, `GPolyMesh`, curves) is a branch with no surface. All 281 observed filters are such. A filter with any other child, and a `GImposter` anywhere else, are walked as before (a decode failure, so the element keeps its box). - `probes/examples/probe_re300_graphics_imposters.rs`, `reports/element-framing/RE-300-light-source-filters.md`, the reconnaissance addendum, `changelog.d/fixed/1247-light-source-filters.md`. ## Testing Unit tests are banned in this repository: do not add them. Show the change working end to end on real files instead. - [ ] `tools/check-local.sh`: CI. - [x] Verified end to end on real Revit files. Measure [41550667212](https://github.com/DrunkOnJava/rvt-rs/actions/runs/41550667212) (6689533 against `main` at a8ad9dd, which reads left-handed cylinders since #1252, `--saved-meshes`): - Office as built: 10,881 → 10,924 bodies drawn from saved meshes (322 → 279 boxes). Scored against Revit's export 1,452 → 1,495; exact to 0.001 ft 1,360 → 1,403. Every new body is exact: 35 wall-mounted and 8 ceiling-mounted "LEX Exit Sign". At permit the same, +43. - RE1 Electrical: +2, both exact. - Snowdon Towers electrical: 907 → 1,324 (556 → 139 boxes). Architectural: 1,971 → 2,303. rme samples: +410 each. - Core Interior and RE1 Architecture, Mechanical and Plumbing are unchanged. - Schema check: only its count of swept solids changes (office 2,404 → 2,361). Snowdon electrical's `--saved-meshes` export passes 30 MB, so IfcOpenShell's full validation skips it, as for any export over that size. - Size: the office as built goes from 447,784 to 473,681 triangles, Snowdon electrical from 41,376 to 815,408. - Before #1252, Measure 41547683034 measured the any-child version of the rule: +39 office bodies, all exact. - [x] A first reading that only skipped the `GImposter` (Measure 41544207306) drew the light's shape with the fixture, at 12 times Revit's volume on the office's exit signs. It is withdrawn; RE-300 §2 records it. - [x] Measure [41550677314](https://github.com/DrunkOnJava/rvt-rs/actions/runs/41550677314) (6689533 against `main` at a8ad9dd, default flags, unfiltered, with the office, R2025, held-out models and samples): all 103 exports byte-identical and the scorer diff empty. No door or window's saved graphics on these files holds a light source, so the change shows only with `--saved-meshes`. 41549448369, at 6afb244, was cancelled when the rule was narrowed. The commit after 6689533 (1f9bb08) changes the report, changelog and addendum only. - Review (Sonnet 5.5 xhigh, automated Claude Code review): no blocking findings. Its notes are applied: - the rule fails closed, applying only to filters of leaves; - the figures are re-measured on `main` with RE-301; - the changelog says `--saved-meshes`; - the samples' new bodies are stated as consistent with light fixtures, not measured; - the report's counts and class list are corrected. - N/A: performance (the same pass, fewer branches). ## Audit-honesty checklist - [x] README / docs reflect the current state after this PR - [x] A user-visible change has its entry as a fragment under `changelog.d/` - [x] Commit messages describe what changed and why - [x] No emojis in code, docs, or commit messages - [x] No private paths, personal email addresses, or internal jargon in committed files - [x] Reverse-engineering finding: probe, report, measured counts against Revit's own export, reconnaissance addendum ## Legal and contribution hygiene - [x] Apache-2.0 - [x] No Autodesk proprietary content - [x] No fixtures Contributor declaration (CLEANROOM.md): based on the saved graphics' own records read from public files (the MIT RE1 models, the CC BY-SA BIM4LCA office, Autodesk's published sample projects) and Revit's IFC exports of them; no Autodesk SDK source, disassembly or NDA material. ## Breaking changes None.
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.
Summary
Saved meshes now read a cylinder whose saved basis is left-handed (
m_xVec × m_yVec = −m_zVec). The tessellator rejected such a face, and RE-224's gate then kept the whole element's box. It is the same cylinder: only ∂P/∂u × ∂P/∂v turns inward, so the normals take that sign, as a plane'sx × ydoes. Vertex positions and winding are unchanged (RE-301).Motivation
#1247 reports that v0.12.0 draws as 12-triangle boxes many elements v0.6.1 drew from saved meshes. It is reproduced on our files (Measure 41537426493: Snowdon Towers electrical 1,420 → 907 bodies, architectural 754 boxes, office 357). Every element lost is RE-224's partial gate. Left-handed cylinders are the largest cause that needs nothing else: 526 elements, 484 blocked by them alone, in the census of Measure 41540910235.
Changes
src/research/native_saved_mesh.rs,cylinder_face: the left-handed rejection is gone; the normals take the basis's handedness.reports/element-framing/RE-301-left-handed-cylinders.mdandchangelog.d/fixed/1247-left-handed-cylinders.md.Testing
Unit tests are banned in this repository: do not add them. Show the change working end to end on real files instead.
tools/check-local.sh: CI.--saved-meshes, againstmain.main, default flags, unfiltered, with the office, R2025 and held-out models.witness_version0.12.0 against 0.12.1 is the only Core Interior change).mesh_bodies_vs_ifc,saved_meshes_vs_ifc,box_bodies_vs_ifc).--saved-meshesthe office as built goes from 331,302 to 447,784 triangles (IFC 70.6 → 75.1 MB) and Snowdon Towers architectural from 648,933 to 974,573 (+12.8 MB). The default export's growth is in the unfiltered run.outwardrenamedhanded, and the reconnaissance addendum. 9ae1285 only renames a variable after the gate's head 148f4cd.Audit-honesty checklist
changelog.d/Legal and contribution hygiene
Contributor declaration (CLEANROOM.md): based on the saved graphics' own fields read from public files and on Revit's IFC exports of them; no Autodesk SDK source, disassembly or NDA material.
Breaking changes
None.