Repository navigation
0.12.0 writes much more of what Revit's own IFC4 export writes, each value
where the model's records show what Revit writes, and leaves a value out
where Revit's own exporters disagree on it.
Base quantities Revit computes from its joined geometry are written where
the records decide them:
- walls' side areas, volumes and
Height, and theGrossFootprintAreaof a
wall nothing joins to or cuts; - the areas and volumes of box-drawn columns nothing cuts or crosses;
- floors'
NetVolumeand flat roofs' slab quantities where nothing cuts
them, and ceilings'GrossArea; - spaces'
NetVolumewhere the room's solid is a prism of its outline; - curtain mullions'
NetSurfaceAreawhere their wall's mullions say which
ends Revit keeps.
A floor's and a covering's Width are left out: Revit 2024's exporter writes
them, later ones do not.
These property values are written:
- unrotated beams'
Roll, level beams'Slopeand theSpanof beams drawn
along their location line (a rotated beam gets noRoll, a sloped one no
Slope); - storeys'
ReferenceandEntranceLevel; - structural columns' and framing's
LoadBearing; - type objects' common sets, without
IsExternal, which Revit's newer
exporters leave out; - a stair's
TreadLengthAtInnerSide, and with--revit-set-placementits
flights'Pset_StairFlightCommon, measured on 14 and 5 stairs; - curtain members'
IsExternalby their curtain wall's value. Exterior
members' values are checked against revit-ifc's source only, since no
newer exporter's model has an exterior curtain wall.
A pipe's InvertElevation is now its height above the model's zero, as
Revit's export writes it.
On the BIM4LCA office as built, counting the objects rvt-rs writes:
- 29,262 of the 39,388 base quantities Revit's export writes are equal
(Measure run 41213779326); - with
--revit-set-placement, 45,235 of the 45,525 property values are
equal (run 41215480967); - 1 differs in each.
What the census counts apart is not in those totals:
- values Revit's export gets wrong (10,390 quantities as built: mullions'
CrossSectionArea, door openings'WidthandHeight, floors'
Perimeter; RE-235 §5); - openings rvt-rs does not write;
- the values the project's own property-set file places;
- the curtain members' values the exporter took from its cache.
No quantity is written that Revit's IFC4 exports leave out. rvt-rs writes 10
property values Revit's export does not as built and 14 at permit:
- 9 and 8 on openings and, at permit, 5 on one column, all on elements
Revit's export does not hold; - one on a fixture Revit's export writes as another class (#792).
docs/release-1.0-criteria.md, W7, has the details.
Native records are read on Revit 2015 to 2022 too: each element's saved
parameters, experimentally, and the phase order, measured against the same
projects saved by Revit 2023. Records that need the extensible-storage
catalogue before Revit 2021, and 2015 to 2017 VarSketch records, are
refused. On Revit 2015 to 2023, experimentally, walls' IsExternal and
ExtendToStructure and structural columns' and framing's IsExternal are
written. They are measured against:
- the same projects' later copies;
- modelo_bim's Revit IFC4 export;
- Revit 2015's IFC2X3 export of BIMcollab's example, passed through an
optimizer and counted apart.
ExtendToStructure's joined value is measured against an export only on
Revit 2024 and 2025.
A model with a partition over 512 MiB no longer loses every value the native
records give. Those readers read under the file's own limits, which
--large-model raises, and name a partition over the limit (#1075). That is
not yet measured on a model over the limits.
Python and the browser viewer draw the doors and windows of Revit 2023 to
2027 files from Revit's saved meshes where the whole mesh decodes, as
rvt-ifc has since 0.11.0. A wall's top is cut at the floor that covers its
whole plan. A wall a floor covers only in part keeps its full height where
Revit steps its top: 29 office walls as built and 26 at permit.
Exports of Revit 2015 to 2023 files take longer. The time comes with the
native records now read on those releases, and is not yet broken down by
stage (#1237). Timed on one runner against 0.11.0 (Measure run 41228075400),
on Autodesk's sample projects:
- 2015 to 2022 projects take 2.1 to 3.9 times as long, 0.9 s to 5.6 s more
each (2.8 to 3.4 times over each release's samples together); - 2023 projects take 1.6 to 2.4 times as long;
- peak memory is up to 19% higher.
Revit 2024 to 2027 exports take as long as before in total per release,
within 4%. Single files take 0.93 to 1.15 times as long, and small ones about
0.1 s more.
The public API that nothing used is removed, and other public types change;
"Upgrading from 0.11" lists each.
AhmadAnzar brought two out-of-date statements in docs/status.md and
ROADMAP.md up to date (#1214), a first contribution. Thank you.
Upgrading from 0.11
- Rust code that names a removed public item stops compiling. "Removed"
below lists each one and what to use instead.rvt::capability's
relation-domain types andifc::NotYetImplementedare gone. FieldType::ElementIdRefhas nosub,referenced_tagno longer keeps
bit 15, andFieldType::encodewrites the reference's six bytes.- Code that builds an
IfcModelwith a struct literal adds
storey_propertiesandtype_entity_sets(Default::default()), and
PropertySet::storey_sets_fortakes the storey properties. rvt-capabilities --jsonwritesschema_version2, without the
relation_domainssection.rvt-schema --jsonwrites nosubon an
ElementIdReffield. The diagnostics'parameter_value_countcounts the
values on type objects too.- Python's
write_ifc()andrvt_to_ifc()draw doors and windows from their
saved meshes. Passsaved_meshes=Falsefor their boxes, as before. - The viewer draws them from saved meshes too, with a File status option.
?savedMeshes=0starts it off, andopenRvtBytesWithDiagnosticsModeAndOpenLimits
takessavedMeshes. - At the default limits the native-record readers stop at 256 MiB, as the
rest of the reader does, where they read up to 512 MiB before. Pass
--large-modelfor a larger partition. - A pipe on a raised storey gets a different
InvertElevation: its height
above the model's zero, not above its storey. - An export no longer writes a floor's or a covering's
Qto_*BaseQuantities.Width, which Revit's exporters disagree on. - Exports of Revit 2015 to 2023 files take 1.6 to 3.9 times as long, 0.9 s
to 5.6 s more on Autodesk's sample projects, with up to 19% more peak
memory (#1237).
Added
-
Unrotated beams'
Pset_BeamCommon.Roll(W7, RE-276). Revit's export
writes a beam's Cross-Section Rotation, in radians, as itsRoll. A
beam's native record holds it in them_rotationof its
FamInstCurveDriver. rvt-rs reads it and writesRoll0 for the beams it
writes an extrusion length for whose rotation is exactly 0: on the BIM4LCA
office, 8 of 8 beams as built and at building permit, each Revit's value. A
rotated beam gets none, as no measured beam is rotated. -
Level beams'
Pset_BeamCommon.Slope(W7). For a beam it exports as an
extrusion, Revit's export takes the slope from a parameter namedSlope,
then from the extrusion's own slope, and otherwise as the angle between the
beam's location line and the horizontal, 0 for a line in the plan. rvt-rs
writes 0 on the beams it writes an extrusion length for whose location line
stays in the plan: on the BIM4LCA office, 8 of 8 beams as built and at
building permit, each Revit's value. A sloped beam gets none, as the
extrusion's slope it would take is not measured. -
Beams'
Pset_BeamCommon.Span(W7). Where it draws a beam as an
extrusion and no parameter gives the span, Revit's export writes the
extrusion's length as the beam'sSpan, the length its
Qto_BeamBaseQuantities.Lengthholds. rvt-rs writes it for the beams it
writes that length for, those drawn along their location line (RE-49): on
the BIM4LCA office, 8 of 8 beams as built and at building permit, each
Revit's value. -
Ceilings'
GrossArea(#1016, RE-297). Revit's export writes a
compound ceiling'sQto_CoveringBaseQuantities.GrossAreaas the area of
the profile its sketch gives, less the cut where Revit cuts it, and a cut
shows in the ceiling's native record as aCutPairGStep. A ceiling drawn
as one extrusion of its sketch whose record holds none carries that area,
its holes taken off: 57 of the 90 values Revit's export writes on the
BIM4LCA office as built and 45 of 75 at building permit, none different.
The area of a ceiling in pieces (Revit's export gives one piece's), of a
cut one and of the office's roofing coverings, ventilation units drawn as
boxes, is not written. -
A box-drawn column's areas and volumes (#1046, RE-291). A column
rvt-rs draws as its record's box, whose type is a plain rectangle (its
length parameters are exactlybandh, orbalone, the box's sides),
carries the box'sCrossSectionArea,OuterSurfaceArea,GrossVolumeand
NetVolumewhen its pair steps are all read and every slab they name lies
wholly above or below it, with no wall or covering cutting it, whether or
not a clean pair joins it. On the BIM4LCA office (Revit 2024, the one
building measured), Revit's export draws a column as a cut mesh, whose
quantities are not the box's, exactly where a slab its cut pair names lies
across an end of it; a round column's type holds aDiameterand gets
none. They are Revit's on all 199 such columns of the office as built and
265 at building permit, none different and none that Revit's export
leaves out: the office goes from 28,329 to 29,125 of the 39,388 quantities equal
as built (Measure run 41203821396). A joined column'sLength, the
round column and the 18 meshed columns stay unwritten (#1203). -
Curtain mullions' and panels'
IsExternalby their curtain wall's value
(W7, RE-288, #1187). Revit'sIsElementExternalgives a family instance
with no parameter and no type Function its host's value, which exporters
from IFC_v24.2.20 on give a curtain wall's members; the exporter that made
the BIM4LCA office's exports caches types instead (RE-269) and is counted
apart. rvt-rs writes each member's curtain wall's value, and none on the
member types: 10,262 values on the office as built, 10,299 at permit and
12 on RE1 Architecture, whose 12 members are equal to its export's (0 of 12
before). Only those three exports change. The exterior members' values are
checked against revit-ifc's source only: no model of a newer exporter has
an exterior curtain wall. -
Floors'
NetVolume(#1016, RE-295). Revit's export writes a floor's
Qto_SlabBaseQuantities.NetVolumeas the volume of its solid: its
GrossAreatimes the total thickness of its type's layers, flat or
sloped, unless something cuts it. A floor whose native record holds
neither aCutPairGStepnor aWallCutoutGStepcarries that. On the
BIM4LCA office that is 31 of the 63NetVolumevalues Revit's export
writes, as built and at building permit, none different and none that
Revit's export leaves out. The volumes of the stair landings Revit draws
as a mesh and of the roofs written as slabs are not written. -
Curtain mullions'
NetSurfaceArea(#1046, RE-268). Revit's export
sums the faces of a mullion's Revit solid, so an end face is not counted
where the mullion meets its own continuation end to end, nor where it stops
inside a crossing mullion, and is counted where it butts against a crossing
mullion's side face. rvt-rs's boxes of a curtain wall's mullions are those
solids, so it reads which ends are kept from where they meet and writes
Qto_MemberBaseQuantities.NetSurfaceAreaas the section's perimeter times
the length plus that many of the section's areas, on the mullions drawn as
an extrusion of their section (RE-243). On the BIM4LCA office that is 6,606
of 10,003 mullions as built and 6,636 of 10,031 at building permit, each
Revit's value. Left out are the mullions with an end that meets a mullion
lying over another, an oblique one, a crossing one that holds the end off
its axis and faces, one shorter than its section or one left out for
these reasons, and every mullion on a curved or edited curtain wall. -
Saved parameters and the phase order are read on Revit 2015 to 2022
(RE-281, #1158).rvt-elementsand Python'sdecoded_elements()list
each element's saved parameters by name on those releases, experimentally,
andrvt-ifc --revit-property-setswrites them. Against the same project's
Revit 2023 copy, 932,645 parameters of Autodesk's sample projects read by
name and value are equal and 243 differ, over 23 projects, each an edit
between the saves.native_element::decode_basetookIdentifierfor
Revit 2024's 8-bytem_id64and refused every Element base of 2015 to
2023, so the project's phase order was not read on Revit 2023 either; it
takes the 4-bytem_idtoo, and the order reads on all 33 sample projects
of 2015 to 2023 with no element left out of the last phase, so no export
changes. A record that needs the extensible-storage catalogue before Revit
2021, or a 2015 to 2017VarSketchrecord, is refused, and every other
native reader (types, stairs, symbol cuts, mullion hosts, ports, saved
meshes) stays on 2023 to 2027. BIMcollab's 16 footings name no Level, so
#879 needs another rule. -
Flat roofs' slab quantities (#1016, RE-298). Revit's export writes a
flat roof as a slab, and gives itQto_SlabBaseQuantities: itsGrossArea
(its sketch's profile's area), itsDepth(the layers' total, however
many there are) andGrossVolume(the area times that depth), and its
NetVolumewhere its record holds no cutting step. rvt-rs writes them on
all 10 of the BIM4LCA office's flat roofs, as built and at building
permit, none different and none that Revit's export leaves out; the roof a
hatch cuts keeps Revit's smallerNetVolumeunwritten, and a roof's
Width(its profile's extent) stays unwritten. A level floor of several
layers gets noDepthorGrossVolume: the office's export (Revit
24.0.5) gives it its last layer's thickness, but Revit 26.4's export of
the held-out Revit 2026 house writes another value on 2 such slabs, so
rvt-rs leaves it out. -
Spaces'
NetVolume(#1016, RE-296). Revit's export writes a space's
Qto_SpaceBaseQuantities.NetVolumeas the volume of the room's closed
shell. Where the room's stored solid is a prism of its outline, every
vertical face running from the floor of its record box to the ceiling and
no face slanted, that volume is the outline's area, its holes taken off,
times the box's height, and rvt-rs writes it. On the BIM4LCA office that
is 167 of the 278 values Revit's export writes as built and 178 at
building permit, and both rooms of each of puzzbobb's six R2025 models
with rooms, none different and none that Revit's export leaves out. The
volume of a room whose ceiling steps (54 as built), of the mapped
accessibility volumes and of the rooms whose outline does not close is not
written; nor isGrossVolume, which Revit's export writes on 88 of the
167 prisms only and which nothing in the file tells from the 79 it leaves
out. -
A stair's
TreadLengthAtInnerSideand flight set (W7, RE-287, #1186).
Revit's export writes on eachIfcStairaPset_StairCommon. TreadLengthAtInnerSideand, by revit-ifc's matching of a set to an entity
by the start of its name, aPset_StairFlightCommonholding the sums of its
flights' risers and treads and their common riser height, tread length,
nosing length and tread lengths at offset and at the inner side. rvt-rs
writes the first always (the stair's tread depth, as a flight's) and the
second withrvt-ifc --revit-set-placement: 111 values on each of the
BIM4LCA office's two files (14 stairs; the spiral stair's tread count is
not read) and 8 on each R2025 stair model, 7 on the spiral one, all equal
to Revit's export's, none different. No other model's export changes. The
mechanism in the exporter that fills the container's flight set is not read:
the rule is measured on 14 and 5 stairs of one to three flights. -
Storeys'
Pset_BuildingStoreyCommon.EntranceLevel(W7, RE-275).
revit-ifc's definition of the set givesEntranceLevelno calculator, so
Revit's export reads a yes/no parameter named
Pset_BuildingStoreyCommon.EntranceLevel, thenEntranceLevel, on the
Level. rvt-rs writes the value the Level's own record holds, where it holds
one: on the BIM4LCA office, as built and at building permit, 9 storeys (the
Level_01 yes, 8 more no) and none for Sea Level, which holds no value, each
Revit's. A file whose Levels declare no such parameter, as the R2025
models', gets none. -
Storeys'
Pset_BuildingStoreyCommon.Reference(W7, RE-275). Revit's
export writes the name of a storey's Level type as itsReference. A
Level's native record names its type inm_attrId, and the type's record
holds the name:Korkomerkintäon each of the BIM4LCA office's 10 Levels,
as built and at building permit, andLevel 1on the R2025 models'. rvt-rs
writes it on each storey, 20 on the office and 110 on the R2025 models, each
Revit's value.IfcModelgainsstorey_properties, by storey index, and
PropertySet::storey_sets_fortakes it. -
LoadBearingon structural columns and framing (#1158, RE-285).
Revit's exporter calls a structural column or structural framing element
load bearing by its category alone. rvt-rs now writes thatLoadBearing
in its common property set on every release, unless a parameter named for
it says otherwise, and on Revit 2015 to 2023, experimentally, the
element'sIsExternal, not external, as the calculation's last step gives
it. Against Revit's exports: BIMcollab's Revit 2015 example 91 of 91 beams
and 15 of 15 columns for each property, and modelo_bim (a Revit 2023 file,
Revit 26.2's exporter) 8 of 8 beams and columns forIsExternaland 9 of 9
forLoadBearing(the ninth on the type objects RE-286 writes); on the
BIM4LCA office as built one column with no such parameter gains Revit's
value. None different, and no new value that Revit's export leaves out. -
Type objects' common property sets (W7, RE-286, #1185). Revit's IFC4
export gives each type object the common set of its entity, with the
properties its entries give the type itself. rvt-rs now writes them: the
type's Fire Rating (RE-77),LoadBearingfor the structural column and
framing categories, and a stair type's and flight type's dimensions (a
stair type'sNosingLength,NumberOfRiserandNumberOfTreadsat 0, in
Pset_StairFlightCommontoo with--revit-set-placement). These are equal
to Revit's export on 34 of the 182 values it writes on the BIM4LCA office's
type objects as built (29 of 154 at permit), on 34 on the R2025 models and
on modelo_bim's column and beam types, none different and none that Revit's
export leaves out. No type object getsIsExternal: the office's and the
R2025 models' exporters write it, Revit's newer ones (the held-out models',
RE1 Architecture's) do not, and nothing in a file says which exporter will
read it.IfcModelgainstype_entity_sets, by type and type entity,
which the writer adds to the type object'sHasPropertySets(code that
builds anIfcModelwith a struct literal adds
type_entity_sets: Default::default()), and the diagnostics'
parameter_value_countcounts a type object'sPset_values. Core
Interior'sIFCPROPERTYSETcount goes from 6,508 to 6,510. -
More roof-joined walls' side areas and volumes (#1046, RE-290). The
longest vertical face of Revit's solid for a plain wall is as long as the
centreline cut back where the wall meets the walls joined at its ends,
which rvt-rs reads wherever both ends agree with the record's join reaches.
A wall joined to roofs, floors or footings that lie clear of it, whose
body is its record's box, now carriesGrossSideArea,NetSideArea,
GrossVolumeandNetVolumewhen that length is its box's long side, not
only when the record confirms itsLength. They are Revit's on all 29 such
walls of the BIM4LCA office as built and 36 at building permit, none
different and none that Revit's export leaves out: the office goes from
28,162 to 28,278 of the 39,388 quantities equal as built (Measure run
41182651693). -
A roof-joined wall's side areas and volumes (#1046, RE-270). A wall
joined to roofs, floors or footings that rvt-rs draws as plain extrusions
lying wholly above its top or wholly below its base (after the top cut at
the floor that covers it, RE-267), with its length confirmed by its record
(the curve cut back at its joins as long as the curve), and no step in its
record but those and a clean join, carries the sameGrossSideArea,
NetSideArea,GrossVolumeandNetVolumeas a wall nothing joins to or
cuts. They are Revit's on all 18 such walls of the BIM4LCA office as built
and 22 at building permit (2 of each cut at a floor), none different and
none that Revit's export leaves out: the office goes from 27,948 to 28,020
of the 39,721 quantities equal as built and from 27,878 to 27,966 at
permit (Measure run 41120485504). A wall a floor passes through, one cut
by a pair or a cutout, or one joined to a sloped roof (the R2025 models')
stays unwritten. -
A wall's side areas and volumes (#1046, RE-270). A wall whose native
record holds no step that cuts, embeds or sweeps it and whose body is its
record's box cut back at its joins, a rectangle, carries
Qto_WallBaseQuantities.GrossSideArea,NetSideArea,GrossVolumeand
NetVolume, as revit-ifc'sCreateWallBaseQuantitiesworks them out of
the wall's solid: the longer side's area, the rectangle times the height,
and the wall type's width times the side area. They are Revit's on all 49
of the BIM4LCA office's such walls as built, 48 at building permit and 91
of puzzbobb's R2025 walls, none different and none that Revit's export
leaves out; the office as built goes from 27,752 to 27,948 of the 39,721
quantities equal, at permit from 27,686 to 27,878 and the R2025 models
from 411 to 775 (Measure run 41108951821). Revit writes the four on
exactly the walls it writes aHeighton, and aNetVolumeon the rest;
the walls with a top join, openings, cut pairs, embedded walls or sweeps
stay unwritten. -
Walls'
Pset_WallCommon.ExtendToStructureon Revit 2015 to 2023,
experimentally (RE-284, #1158). Whether a wall's top is joined to a roof
or floor is read from its native record (aJoinToRoofGStepwith
m_baseOrTop1), as on Revit 2024 and 2025. Against the same project
saved by a later release it is equal on all 1,983 walls both files hold,
over 24 pairs of Autodesk's sample projects of 2015 to 2022 and their 2023
copies, with both values present (124 of the 2015rac_advanced's 180 walls
are joined). Revit's own exports agree on the 114 walls of BIMcollab's
Revit 2015 example and the 4 of modelo_bim, which are all not joined; the
joined value is measured against an export only on 2024 and 2025. A wall's
height, top cut and side quantities are still read from 2024 on. -
A wall's
GrossFootprintArea(#1046, RE-292). A wall nothing joins
to or cuts, whose body is its record's box cut back at its joins and that
is more than three times as long as it is thick, carriesGrossFootprintArea,
its length times its width, beside the side areas and volumes it already
gets. Revit's export writes it on the walls it draws as an extrusion, and
it is Revit's on all 48 such walls of the BIM4LCA office as built, 47 at
building permit and 91 of the R2025 models', none different and none that
Revit's export leaves out (the one wall as long as it is thick, which it
gives none, is not written): the office goes from 28,162 to 28,210 of the
39,388 quantities equal as built (Measure run 41183025562). Walls joined to roofs
or floors get one from Revit on 78 of 85 as built and nothing in the
record tells which, so they stay unwritten. -
A roof-joined wall's
Height(#1046, RE-293). A wall joined to roofs,
floors or footings that lie clear of it, which getsGrossSideArea,
NetSideArea,GrossVolumeandNetVolumefrom its record's box (RE-270,
RE-290), now also carriesQto_WallBaseQuantities.Height, the body's:
Revit's export writes it on exactly those walls, and rvt-rs's extrusion is
as tall as Revit's solid on every one. 47 more walls of the BIM4LCA
office as built and 58 at building permit carry it, Revit's on every
one, none different and none that Revit's export leaves out: the office
goes from 28,278 to 28,492 of the 39,388 quantities equal as built
(Measure run 41183229365). -
Walls'
IsExternaland the parameters named for a standard property
on Revit 2015 to 2023, experimentally (RE-283, #1158). A wall's type
Function (BasicWallType.m_function) is read from its native records on
those releases, and the project and shared parameters namedIsExternal,
<set>.IsExternalor for a property of one of IFC4's sets are read from the
saved parameters, so a wall'sIsExternaland those properties are written
as on 2024 and 2025. The Function is equal to the same project's later
copy on 1,982 of 1,983 walls over 24 pairs of Autodesk's samples (the other
is an edit between the saves). Revit's own exports agree on the 114 walls of
BIMcollab's Revit 2015 example (IsExternalandLoadBearing, which two
parameters on its walls give) and the 4 walls of modelo_bim, a Revit 2023
file (IsExternal, from the Function), none different. Doors, windows and
slabs get none: their Function is not read on these releases.
Changed
-
FieldType::ElementIdRefis a class reference and nothing more
(#1101, the maintainer, 2026-10-30). A schema field's by-value reference
is the type word0e 00 00 00and au16naming the referenced class,
six bytes; where its bit 15 is set the class is defined inline after it.
The variant'ssubread the two bytes after those six, which belong to
whatever follows: the next field's name length on about 1,900 fields of a
2024 to 2026 schema, the pad before an inline definition on about 240,
and a class's GUID-list count on about 600.subis gone from
ElementIdRefand fromrvt-schema --json,referenced_tagno longer
keeps bit 15, and every reference to the rootElementIdclass reads as
ElementId, where that used to depend on the next field.
FieldType::encodewrites the six bytes. Code that namessubstops
compiling: drop it. No export changes (Measure run 41102077364, every
reference model, the R2025 models, Autodesk's samples and the family
corpus); the walker's schema scan finds fewer low-confidence candidates,
which the default export already left out, so the diagnostics count fewer
suppressed ones (1,138 to 91HostObjAttron Autodesk's 2027 MEP sample,
on 39 files in all). -
A pipe's
InvertElevationis the height above the model's zero, and a
Revit 2024 vertical pipe has one (W7, RE-157). Revit's export writes the
lower end's height in the model's frame, not above the pipe's storey: the
BIM4LCA office's 12 vertical pipes stand on a storey 55.5 m up and carry
55.32 m. RE1's pipes are all on the storey at zero, which hid the
difference. rvt-rs no longer takes the storey's elevation off, and a
vertical pipe's invert, its lower end, no longer waits for an inner
diameter that Revit 2024 pipes do not have read, so the office's 12 pipes
as built and at building permit have Revit's value where they had none. -
The property census counts curtain members'
IsExternalapart, as the
exporter's own output (W7, RE-269). The exporter that made the BIM4LCA
office's exports gives a curtain mullion or panel its curtain wall's
IsExternaland then caches each member type as not external, so every
later wall's members of that type read false: a value the model does not
hold, which rvt-rs does not write (the maintainer, 2026-10-30).
tools/re/psets_vs_ifc.pyno longer counts those values as missing, nor
the mullion types' own: 10,267 on the office as built (10,003 mullions,
260 panels, 4 mullion types) and 10,304 at building permit are listed
apart, with the other values Revit's export gets wrong (RE-235 §5). It
counts them only where the export's own type objects hold the value, so
RE1 Architecture's 12 members, exported by a later exporter, are still
scored. On the office as built the census goes from 12,672 missing of
57,773 to 2,405 of 47,506 with--revit-set-placement, and from 13,638
to 3,371 without it; equal (45,045 and 44,079) and different (56) do not
move, and no export changes. -
The property census counts what a project's own export-time property set
file places apart, as out of W7's scope (RE-239). The maintainer ruled
those values out of scope on 2026-10-26;tools/re/psets_vs_ifc.pynow
lists them apart instead of as missing: in an IFC4 Reference View export,
the glazing set on elements that are not doors or windows, and the space
occupancy set. On the BIM4LCA office as built that is 1,981 values (1,907
at permit); with--revit-set-placementthe census's missing values go
from 2,381 to 455 and its different ones from 56 to 1, and equal is
unchanged on every model. No export changes. -
psets_vs_ifcscores each opening against the opening it corresponds to
(W7). Revit's export writes several openings with oneTag, the
ElementId of the element they belong to: a door drawn as an opening, filled
by its door, and, in each further wall or door that element cuts, an
opening with no filling that holdsPset_OpeningElementCommon.Reference
andFireExit. Keyed byTagalone, the census scored those values
against rvt-rs's filled opening, or against a curtain wall that shares the
Tag, and listed them as missing: on the BIM4LCA office as built, 140
Referencevalues and 31FireExitvalues that sit on openings rvt-rs
does not write (a curtain wall's 69 cuts, 39 fire hose cabinets' and 31
door openings' cuts in further walls). An opening is now keyed by whether
something fills it, and the values on openings rvt-rs does not write are
counted apart, not dropped. -
Python draws doors and windows from their saved meshes, as
rvt-ifc
does. Since 0.11.0rvt-ifcandrvt-gltfdraw the doors and windows
of Revit 2023 to 2027 files from the meshes Revit saved for them, where all
of a mesh decodes; Python'swrite_ifc()andrvt_to_ifc()still drew
their bounding boxes, so the same file gave a different IFC (found checking
the 0.11.0 wheel against the CLI). They now draw the same bodies, and
export_diagnostics(),export_diagnostics_json()and
rvt_to_ifc_diagnostics()describe that export.saved_meshes=Falseon
each keeps the boxes, asrvt-ifc --no-saved-meshesdoes; a
RuntimeWarningsays when the saved graphics could not be read.
rvt::ifc::saved_meshes::default_scopegives the default to Rust callers. -
The quantity census keys an opening by whether something fills it, as
the property census does (#1161).tools/re/qtos_vs_ifc.pykeyed every
opening by itsTagalone, so the further cuts Revit's export writes for
a door or a curtain wall were scored against rvt-rs's door opening. Each
opening now carries the classes of what fills it, so a door's opening is
still known for RE-235 §5's swappedWidthandHeight, and the
quantities on openings rvt-rs does not write are counted apart (#1165).
On the BIM4LCA office as built that line lists 527 quantities (some of
them were hidden before, a later opening of the sameTagoverwriting an
earlier one); missing goes from 11,700 to 11,367, the swapped door-opening
WidthandHeightset aside from 191 to 187 each (the 4 others are a
door's further cuts), and equal and different are unchanged on every
model. No export changes. -
The viewer draws doors and windows from their saved meshes, with a
toggle. Since 0.11.0rvt-ifcandrvt-gltfdraw the doors and windows of
Revit 2023 to 2027 files from the meshes Revit saved for them, where all of a
mesh decodes; the browser viewer still drew their bounding boxes, so the
model on screen, its glTF and its IFC differed from the command line's for
the same file. It now draws the same bodies, and File status has a "Draw
doors and windows from saved meshes" option, on by default; changing it
reopens the open file, and?savedMeshes=0in the address starts with it
off.openRvtBytesWithDiagnosticsModeAndOpenLimitstakessavedMeshesfor
it. The cost, measured in Playwright (Chromium on a 4-CPU runner, one open
each,tests/saved-meshes-measure.spec.ts, which Deploy viewer runs and
uploads): Core Interior (32 MiB, 138 doors and windows, all drawn from
their meshes) loads in 25.6 s against 24.5 s with boxes, and the wasm
memory after the load is 324 MiB either way; Einhoven and RE1
Architecture load 0.1 s and 0.3 s slower with the same memory, and the three
RE1 models with no doors or windows read nothing extra.
Fixed
-
A partition over 512 MiB no longer stops every reader of native records
(#1075). The readers
of native records (types, materials, stairs, phases, saved parameters and
others) kept a stream cap of their own, 512 MiB, that--large-modeldid
not raise. A model with a larger partition got none of their values, not
only that partition's, and the diagnostics did not say so. They now read under the file's own
limits:--large-modelraises theirs too, and a partition over the limit is
named in the diagnostics and skipped while the rest of the file is read.
An element whose current record sits in that partition is left out rather
than read from an older copy in another partition. At
the default limits they now stop at 256 MiB, as the rest of the reader
does, where they read up to 512 MiB before. Not yet measured on a model
over the limits: a contributor's model with a 1.33 GB partition (#1117) is
the first such file. -
A wall's top is cut at the floor that covers it (RE-267, #1067). A wall
whose top join or Join Geometry pair names a slab, roof or footing is drawn
up to that element's underside when the element's outline covers the whole
of the wall's plan, clear of its holes and openings, as Revit's export draws
it: on the BIM4LCA office 64 of the 65 tops Revit cuts as built and 70 of 70
at building permit are now Revit's, no other wall's base or top moves, and
the exports of Core Interior, RE1 Architecture and the R2025 models are
byte-identical (Measure run 41092512565). A wall that a floor covers in part
keeps its full height, where Revit steps the top (29 office walls as built
and 26 at permit), and so does the one wall as built whose plan lies
0.0243 ft² outside the floor and which Revit cuts all the same. A cut wall
carriesBodyHeightSourcewall_top_cut_at_covering_floorand
TopCoverElementId, the element it is cut at, and noHeight, which
Revit's export omits on 2 of them as built and 4 at permit.
Removed
-
rvt-capabilitiesno longer lists relation domains, and
ifc::NotYetImplementedis gone (the maintainer, 2026-10-30). The
capability manifest'srelation_domainssection and its
relations.typed_domainsrow described the typed-relation module that
0.11.0 removed (#1131): the row claimed a registry and "SCC/condensation/
quarantine stubs exist", which was no longer true. The section leaves
rvt-capabilities(text and--json) and
docs/schemas/capability-manifest.schema.json, whoseschema_versionis
now 2 (a consumer that reads version 1 sees the section is gone), and
rvt::capability::RelationDomain,RelationDomainRegistry,
RelationDomainEntryandDomainStatusleave the API. Nothing replaces
them: no code read or wrote a relation domain.ifc::NotYetImplemented,
an error no exporter returned, goes with them. Two remaining rows of the
manifest say in plain words what they meant: nothing reads the compound
ArcWall variant's openings, and remapping Extensible Storage ElementIds
needs Revit API output the project does not have. -
A floor's and a covering's
Width(#1046, RE-294). Revit 2024's
exporter (24.0.5) writesQto_SlabBaseQuantities.Widthon a compound
floor andQto_CoveringBaseQuantities.Widthon a ceiling and on a wall
it exports as a covering; the exporters that wrote two held-out models (a
Revit 2025 and a Revit 2026 file) write none on them, so rvt-rs wrote
values Revit's export omits there. Where Revit's exporters disagree on a
value, rvt-rs leaves it out, and these are no longer written, including
the ceilings'Widthof 0.11.0 (RE-250): the BIM4LCA office loses 113
quantities that were equal as built and 89 at building permit (they
become missing, none different), and the held-out models go from 2 and 3
values Revit's export omits to none (Measure run 41204218380). -
Public API nothing in the workspace used is removed, as planned before
1.0 (the maintainer, 2026-10-30). No exporter, CLI, binding, test,
example, benchmark or fuzz target called these, so 1.0 doesn't promise
them. Most were convenience wrappers over fields that stay public:Floor::is_depressed,Door::is_flipped,Window::sill_height_inches,
Wall::is_unconnectedandWallType::width_inches: read the field
they wrapped.WallKind::is_basicandWallFunction::to_ifc_predefined: match on the
enum.FloorBoundaryLoop::area_sqftandto_curve_loop: the loop's points
stay public, so compute the area from them.Extrusion::t_shape,l_shape,u_shape,rectangle_hollow,
circle_hollowandarbitrary_with_voids: build theProfileDef
variant directly.MaterialLayerSet::total_thickness_feet: sum the layers.ifc::category_map::is_ifc_member,EvidenceTier::meets_verified_gate,
InflateShortfall::is_completeandRoundTripReport::is_typed_clean.RevitFile::preview_png_untrimmed,preview_rawand
transmission_data_probe:preview_pngremains, and
transmission_data::probe_transmission_datais what the last one
wrapped.WalkerControl::cancel_token: keep a clone of theCancelTokenyou
pass towith_cancel.SchemaTable::tagged_ancestor_map,walker::encode_adocument_fields
andADocumentInstance::elem_table_pointer.
Research
-
Why Revit's export writes
IsExternaltrue on 528 curtain members
(RE-269, #35). The value is not in the model: revit-ifc's
IsElementExternalgives a curtain mullion or panel its curtain wall's
value, and the exporter that made the BIM4LCA office's exports (24.0.5.432)
also caches each member type as not external once the first wall that uses
it is done, so every later wall's members of that type read false. Replaying
that cache over the walls in ElementId order is Revit's value on all 10,263
members and panels of the office as built (498 mullions and 30 panels true)
and all 10,300 at building permit, none different; the host rule is Revit's
on 1,651 and 1,691. rvt-rs still writes noIsExternalon curtain mullions
and panels: the exporter version is not in the model, and exporters from
24.2.20 on do not cache types. A probe lists each member's type, host and
the host's Function, andtools/re/member_is_external_cache_vs_ifc.py
scores both rules and prints the export's exporter version. -
Reading an ElementId in a 4-byte
Identifierin every native reader
moves three Revit 2023 exports no export checks (RE-282, #1158). Revit
2015 to 2023 saveIdentifieras a 4-bytem_id, 2024 and later as an
m_id64, and every native reader but the Element base and the phase order
reads only the second. Reading both shapes everywhere leaves 91 of 94
exports byte-identical on Measure's unfiltered run (all 30 samples of 2015
to 2022, BIMcollab, the held-out models, all 25 samples of 2024 to 2027,
the R2025 models, the offices, Core Interior and RE1) and moves Einhoven
and two of Autodesk's 2023 samples: 36 and 30 connector ports, a wall
layer set and material associations appear that nothing measures on
Revit 2023. So each reader is
admitted to 2015 to 2022 on its own measurement, reading the ids it needs
itself, and the other readers stay silent on 2023. -
The native record framing holds on Revit 2015 to 2022 (RE-280, #1158).
On Autodesk's 30 sample projects of those releases and BIMcollab's
Revit 2015 example, every one of 27,762 record groups frames under the
layout Revit 2023 uses (au32id, a word, the length, the body and the
length again), the five global streams parse (the extensible-storage
catalogue on 22 of 31), and 98.8 to 100 per cent of the declared
elements' object graphs decode, with the owner id agreeing on every one.
Before Revit 2018 a group's declared body size counts each record's
trailing length word, on all 12,005 groups of 2015 to 2017. Against the
same project's 2023 copy, every ElementId both files hold has the same
class on 23 pairs, and every saved parameter of 2021 and 2022 has the same
value. Nothing is admitted yet:native_element::decode_baserefuses
Identifieras 2015 to 2023 write it (a 4-bytem_id), which also keeps
the phase filter from reading Revit 2023, and the extensible-storage
catalogue needsm_specTypeId, which 2021 introduced.
probes/examples/probe_re280_native_framing_pre2023.rsis the measurement. -
Three BIM4LCA office properties the file does not decide (W7, RE-277).
Columns'Pset_ColumnCommon.Slope(73 of 279 as built, 101 of 345 at
permit, all 0.0) comes from the last geometry object Revit's exporter sees
for the column, and the file does not fix it: six columns have a native
record identical in both files and Revit gives them the property only at
permit, and twelve identical columns on one level split 5 to 7 by whether a
join is user-set. The building'sReference(Project Information) is a
string the file does not hold. The door openings' 140Referenceand 31
FireExitvalues are on the openings Revit writes where a door cuts a
further wall, which rvt-rs does not write. None is written. The probe
probe_w7_office_gapslists each Level's, beam's, column's and pipe's
native record for the office and the R2025 models. -
What Revit's wall areas and volumes are (RE-270, #1046). In revit-ifc
24.1 and 24.2 (the office's exporter) a wall'sGrossSideAreais the
largest vertical face's outer boundary andNetSideAreathe largest face
with its holes out, the solid's volume isNetVolume, andGrossVolumeis
the wall type's width times theGrossSideArea. Worked out of Revit's own
bodies they give 435 and 430 of the office's 579 walls as built (grouping
the faces by normal, as 25.2 does, gives 270 and 276) and all 138 of the
R2025 models';GrossFootprintAreaisLengthtimesWidthon all 279
walls that carry it. Revit writes the four on exactly the walls it writes
aHeighton, andNetVolumeon every wall, 28 more as built.
tools/re/wall_quantities_vs_ifc.pyis the measurement. -
Revit cuts a wall's top only where the floor covers it (RE-267, #1067).
The 5 walls per stage that RE-258 found Revit leaves whole are cut over the
part of their plan the floor covers and left at full height over the rest,
so the highest point does not move: on the BIM4LCA office the area of
Revit's body at the wall's full height equals the wall's plan outside the
floor on 79 of 83 walls as built and 83 of 87 at permit. A rule that cuts a
top where the floor named by its top join or a cut pair covers the wall's
whole plan gives 64 of the 65 cut tops as built and 70 of 70 at permit,
and cuts no wall Revit leaves whole; one wall's 0.085 ft stub past the
floor's edge is cut by Revit and unexplained, and a part-covered wall
needs a stepped top, which this export does not draw.
tools/re/wall_top_cover_vs_ifc.pyand
probes/examples/probe_1067_native_dump.rsare the measurement.
User guide: https://github.com/DrunkOnJava/rvt-rs/blob/v0.12.0/docs/user-guide.md