Part II. Language
This part defines the records. Each record kind has a JSON Schema in schemas/; the schema fixes the members and their types, and this text fixes what they mean and the rules a schema cannot state. A record MUST validate against its schema, and MUST meet the rules of this part.
1. The record kinds
| Kind | One per | Stored at (Part III) | Schema | Group |
|---|---|---|---|---|
| Project | model | project/project.json | project/project.schema.json | core |
| Levels | model (one list) | project/levels.json | project/levels.schema.json | core |
| Order | model | project/order.json | project/order.schema.json | core |
| Grid | grid line | project/grids/<id>.json | project/grid.schema.json | core |
| Material | material | project/materials/<id>.json | project/material.schema.json | core |
| Type | type | types/<discipline>/<category>/<id>.json | types/<category>.schema.json | core |
| Element | element | <discipline>/<level>/<category>/<id>.json | elements/<category>.schema.json | core and domain profiles |
| Original | placed group | project/originals/<id>.json | project/original.schema.json | core |
| Copy | placement of a group | project/copies/<id>.json | project/copy.schema.json | core |
| View | view | drawings/<discipline>/views/<kind>/<id>/view.json | drawings/view-record.schema.json (drawings/view.schema.json with its items inline) | documentation profile |
| View detail chunk | up to 256 detail items | drawings/<discipline>/views/<kind>/<id>/details/<n>.json | drawings/view-details.schema.json | documentation profile |
| Scope box | scope box | project/scope-boxes/<id>.json | project/scope-box.schema.json | documentation profile |
| Dimension style | style | project/dimension-styles/<id>.json | project/dimension-style.schema.json | documentation profile |
| Detail family | 2D family | project/detail-families/<id>.json | project/detail-family.schema.json | documentation profile |
| Piece | fabricated unit | fabrication/pieces/<id>.json | fabrication/piece.schema.json | fabrication profile |
| Joint | structural joint | fabrication/joints/<id>.json | fabrication/joint.schema.json | fabrication profile |
| Sheet, title block, image, report, render, deviation, area adjustment, linked reference | record | Part III, section 3 | application-record.schema.json | application records |
The order is listed for its file and its schema: it is an index of the record lists, not a record, and the single-file form has none (Part III, 9, rule 5, and 11).
Reference: manifestSchema in src/core/model/model.ts (the lists and their record schemas); recordLists and listFolders in src/core/versions/layout.ts.
2. The project
project/project.json holds:
schemaVersion:1(Part I, 9.3);project:{id, name, units: "mm", upAxis: "Z"}and optionallyelevationOffset(the project's zero above a shared datum, in mm),site(latitude, longitude, true north in degrees clockwise from plan +Y, an IANA time zone),rooms(room measuring rules),excavationandprecast(rules for those profiles),standards(drawing standards: an application value) andenvelope(the envelope's air leakage and thermal bridges, section 2.1);projectInformation(optional): values shown on drawings.
A model SHOULD give its site with trueNorth: without it, plan +Y is taken as north (section 6.8), which is right only by chance, and an energy balance cannot place the sun. In 0.1 a site gives all four of its members, so a writer that knows true north but not where the site lies cannot give it; from 0.2, trueNorth may be given alone (decided on 22 October 2026; open questions, 44), as section 2.2 says.
A site's latitude and longitude name the plan's origin: the point [0, 0] of every profile, at the project's zero, the height 0 that levels' elevations are measured from (section 3), which lies elevationOffset above the shared datum. True north lies trueNorth degrees clockwise from the plan's +Y about that point (section 6.8). 0.1 names no coordinate reference system, the map grid in which a surveyor gives eastings and northings, nor a vertical datum: a bridge that places the plan on such a grid takes them from its caller (Part VIII, 1). By the steward's decision of 26 October 2026 (open questions, 79), 0.2 adds an optional site.crs that names both by their EPSG codes, as section 2.2 says.
project.id is the project's identity. Like every id it is stable for the life of the project (Part I, 6): every version, alternative and copy of the folder keeps it. IFC GlobalIds are derived from it (Part VIII), so an element keeps its GlobalId across them.
2.1 The envelope
envelope is {airLeakage?, thermalBridges?}, the values of the thermal envelope as a whole that an energy balance needs and no element carries:
| Member | Unit | Meaning |
|---|---|---|
airLeakage | l/(s·m²) | the envelope's design air leakage at a pressure difference of 50 Pa, q50, per m² of the envelope's area (EN ISO 9972) |
thermalBridges | a list, at most 1000, of {kind, psi, name?}: the linear thermal transmittance psi in W/(m·K), from −2 to 5, of the junctions of one kind (EN ISO 14683, EN ISO 10211) | |
dimensions | which dimensions the psi values refer to: internal, overall-internal or external (EN ISO 13789). A ψ differs with them, so it SHOULD be given with thermalBridges |
The lengths are not stored: a tool measures them from the elements where the junctions are (section 10), in the dimensions dimensions names. A thermal bridge's kind is a plain string, and two thermal bridges MUST NOT have the same kind: a tool would not know which ψ to take. So that every tool measures the same junctions, a kind SHOULD be one of these names:
| Kind | The junction |
|---|---|
wall-ground-slab | an exterior wall on a slab on the ground |
wall-roof | an exterior wall to a roof |
wall-intermediate-floor | an exterior wall past an intermediate floor |
opening-in-wall | around a window or a door in an exterior wall |
outer-corner, inner-corner | where two exterior walls meet, outside or inside |
balcony | a balcony slab through an exterior wall |
A kind may also be a designation of EN ISO 14683 with its number (GF1, W8), the junction of that standard's catalogue: a tool reads it only if it knows the catalogue. A corner is better named outer-corner or inner-corner, which says which it is without the catalogue. A tool that does not know a kind SHOULD say so, and not guess its length. The envelope is set with project.envelope (Part V, 2.1).
2.2 The site
Part of 0.2. OpenEik 0.1 had it as the proposal site: in a model of 0.1, read by 0.1's rules (Part I, 9.6, rule 3), a site gives all four of its members, and crs is a member a schema of 0.1 does not know, which a reader keeps (Part I, 10). The section adds one member, site.crs, and no file.
By the steward's decisions of 22 October 2026, asked by an analysis application (open questions, 44: rules 1 and 2), and of 26 October 2026 (open questions, 79: rules 3 to 5).
True north alone. A
siteMAY givetrueNorthalone. Itslatitude,longitudeandtimeZoneare its location: a site gives the three together or none of them, and a site that gives its location givestrueNorthtoo. So a site is{trueNorth}, or all four. A validator reports a site that gives part of its location, or its location withouttrueNorth, as its schema's error.A site without a location says which way north is, and nothing of where the site lies. Its true north is read as section 6.8 reads it. A tool that needs the location, an energy balance that places the sun or a bridge that places the plan on a map, has none, and SHOULD say so rather than assume one. A bridge that writes IFC writes the true north of its context and no latitude, longitude or map conversion.
Its coordinate reference systems. A site that gives its location MAY give
crs,{horizontal, vertical?}, each the code of a coordinate reference system in the EPSG registry, writtenEPSG:and the number without a leading zero:horizontalthe projected system, the map grid, in which a surveyor gives eastings and northings, andverticalthe vertical system in which heights are given. A site MUST NOT givecrswithout its latitude and its longitude; a validator reports it, and a code of another form, as its schema's error. OpenEik lists no systems, and does not check that a code is one the registry gives: its publisher, the registry, does.What it says. The latitude and the longitude stay the site's place: the plan's origin
[0, 0](above).crs.horizontalnames the grid a bridge projects that place into, and where the site givescrs.vertical,elevationOffsetis the height of the project's zero in that vertical system. A writer that is given a surveyor's eastings and northings in a grid turns them into a latitude and a longitude, and names the grid incrs.horizontal, so that the model holds one place: it holds no eastings and northings beside the latitude and the longitude, which could disagree with them.A bridge that places the plan on a map projects the latitude and the longitude into
crs.horizontal, and turns the plan's x axis by true north and by the grid's convergence there, the angle from true north to the grid's north; Part VIII, 1.7 says how IFC writes it. A bridge that cannot project the system says so in its fidelity report, and writes no map conversion. Which systems a bridge projects is the bridge's: a code it does not know is no error of the model.
A tool that reads a plan drawing with a north arrow, and nothing of where the building stands, writes "site": {"trueNorth": -12.5}: north lies 12.5° counter-clockwise from the plan's +Y. A project placed in SWEREF 99 TM, its heights in RH2000, writes "site": {"crs": {"horizontal": "EPSG:3006", "vertical": "EPSG:5613"}, "latitude": 57.70887, "longitude": 11.97456, "timeZone": "Europe/Stockholm", "trueNorth": 0}, and "elevationOffset": 12500 when its zero lies 12.5 m above RH2000's.
3. Levels
project/levels.json is the list of levels in their stored order, at least one. Each is {id, name, elevation}. Level ids MUST be unique. Level order in the file is the order a writer keeps; readers MUST NOT infer elevation order from it.
4. Materials
A material is {id, name, color, pattern, revision} with optional surface (a projected surface pattern: brick, boards, panels and others) and the optional physical values of section 4.1. id matches ^[A-Za-z0-9_-]{1,60}$.
- A layer names its material by name: a layer's
materialtext matches the material whosenameis equal to it, ignoring case and surrounding white space. - A layer whose material text matches no material is valid: its material is that text alone.
- A layer of a type that has an
insulationlayer SHOULD have a design thermal conductivity: its own (thermal.lambda, section 5.1) or its material'slambda. A membrane and an air layer (one withthermal.air) need none: EN ISO 6946 gives an air layer its own resistance. In 0.1 an insulation layer marks a part of the thermal envelope, since a model does not yet say which parts face the outside. - The cut pattern
clt(of 0.2; section 14). A material'spattern, the hatch its cut is drawn with, and a layer's own (section 5.1), MAY beclt, cross-laminated timber's, beside the patterns of 0.1. A drawing draws it as it draws the others: how a hatch looks is the drawing application's. In 0.1 it is a value the schemas refuse; a validator of 0.2 takes it (open questions, 115).
Reference: materialNamed in src/core/assemblies/materialLibrary.ts and its use in src/core/geometry/geometry.ts.
4.1 Physical values
The values that building physics, structure, fire and climate tools read from a material, all optional. Where a value comes from a standard's classes, it is a plain string (section 8, rule 3).
| Member | Unit | Meaning |
|---|---|---|
lambda | W/(m·K) | the design thermal conductivity, as a calculation uses it (EN ISO 10456); greater than 0, at most 1000 |
density | kg/m³ | the density ρ of the material itself (EN ISO 10456): plain concrete's, not reinforced concrete's; greater than 0, at most 30 000. It is no structural unit weight (below) |
specificHeat | J/(kg·K) | the specific heat capacity c; greater than 0, at most 20 000 |
vapourResistance | the water vapour diffusion resistance factor μ (EN ISO 10456, EN ISO 13788); from 1 to 10⁹. A membrane whose thickness is nominal gives its layer's thermal.sd instead | |
solarAbsorptance | α of an outer surface, from 0 to 1 | |
emissivity | ε of a surface that faces an air layer, from 0 to 1 (EN ISO 6946, annex D) | |
lightReflectance | the visible light reflectance of an inner surface, from 0 to 1, for daylight | |
criticalMoisture | % | the critical relative humidity at which the material risks mould or damage, greater than 0, at most 100: the critical moisture state that a moisture safety design checks against |
fireReaction | the reaction to fire class (EN 13501-1), such as A1, B-s1,d0 or Dfl-s1 | |
strengthClass | the strength class or grade (EN 338, EN 14080, EN 206, EN 10025, EN 10080), such as C24, GL30c, C30/37, S355 or B500B. A member's section states its own grade, which decides where the two differ (section 5.2, rule 6) | |
climate | {gwpA1A3, unit, source?}: the global warming potential of modules A1–A3 in kg CO₂e per declared unit, the unit (kg, m3, m2, m or piece), and where it comes from (an EPD's identifier, EN 15804, or a climate database's) |
A writer that has a value from a declaration rather than a design value says so in the material's name or in an extension member (Part I, 11); lambda is the value a calculation uses.
density is the material's own density, the ρ that a heat capacity, a moisture calculation or a mass reads. It is no structural unit weight: a self-weight for structural design includes what the material carries as built, such as the reinforcement in concrete, and is a weight per volume, in kN/m³.
5. Types
A type is the shared definition its elements follow, as a class is for its instances. Every type has:
| Member | Meaning |
|---|---|
id, name | identity and display name |
category | one of the thirty-one element categories; only elements of this category may use the type |
material, color | the type's material text and display colour (#rrggbb) |
width, height | the type's nominal size in mm, positive. The size its elements take only where the type sets it (section 5.3): a door's or window's type with a windowFamily or openingFamily, a type with a component (other than a contour plate's, a bolt group's or a weld's) or an insert, a round footing type. A door or window whose type has neither family keeps its own size |
layers | optional: the compound layers (section 5.1) |
revision | optional; absent means 0 |
and at most a few payloads, each allowed only for some categories:
| Payload | Allowed for | What it defines |
|---|---|---|
layers | slab, wall, foundation, roof, ceiling | compound layers |
section | beam, column | a member section: rectangle, I, T, RHS, CHS, round, L, 2L, U, sheet or custom, with width, depth, web, flange, and a custom section's outline (section 5.2) |
framing | beam, slabEdge | a parametric framing family (section 5.4) |
edgeProfile | slabEdge | an edge beam's or an edge form's section (section 5.6) |
gutterProfile | gutter (required there) | a gutter's section (section 5.6) |
windowFamily | window | a window family; the profiles of its frame and its mullions are 0.2's (Part IV, 4.3.1, rule 15) |
openingFamily | door, window | a door or window family; the opening's kind decides which. Its material is its frame's: wood, aluminium, aluClad (aluminium-clad wood) or steel (open questions, 89); a door's leafMaterial, its leaves' where it is not the frame's, is 0.2's (Part IV, 4.3.1, rule 14), and so are the profiles of its frame, its mullions and its sashes (rule 15) |
outline | types with an openingFamily | a polygonal opening shape |
wallAttach | wall | defaults for attached wall tops |
footing | foundation | a round footing; the type's width equals its diameter |
component, voidForm, edgeDetail, insert | component | a component, a void, an edge detail or a cast-in item; a component type MUST have one of them |
room, shaft, stair, railing, pipe, duct, terminal, furniture, planting, fire, road, parking | their categories | the domain data of those categories |
generic | generic (required there) | what the type stands for, its IFC class and its discipline (section 6.6) |
thermal | slab, wall, foundation, roof, ceiling, door, window | declared thermal values (section 5.5) |
acoustic | wall, slab, door | declared sound insulation (section 5.5) |
assembly, catalogSource, handbook | any | application values (section 9.2) |
declaredGeometry | any | a supplier's geometry at a declared level of detail (section 12.1) |
A type MUST NOT carry both openingFamily and windowFamily. The category-specific schemas types/<category>.schema.json encode the table above.
A terminal type's terminal.kind is one of the kinds types/type.schema.json lists, from air terminals and units to sanitary fixtures, appliances and radiators; chilledBeam is an active chilled beam. unitHeater is a unit heater, and the kinds of components in a pipe or a duct are section 6.9's. A terminal type's terminal.mount is ceiling, wall, floor, roof, duct for a component in a duct, or pipe for a component in a pipe (section 6.9).
A component's family. A component type's component.family says what its elements are: plate a steel plate, bolt a bolt group, weld a weld, angleBracket an angle bracket, joistHanger a joist hanger and timberSection a piece of a timber section; toilet and basin are sanitary fixtures of before 0.1, read in 0.1 and deprecated in 0.2, which a terminal now stands for (open questions, 73). Its depth is its third size in mm, beside the type's width and height: a plate is width by depth in its own x and y, and its thickness is its height. A bracket's or a hanger's sheet is thickness thick, a hanger's flange is the width of each of its nail flanges, folded outwards where it is positive and inwards where it is negative, and a punched connector's nails are in the pattern nails. A plate type's holes go through each of its plates, each centred at x and y in the plate's own frame, diameter across, and slotted where it gives a length, its length overall, along angle degrees from x, its ends round. Part VIII, 1 names each family's IFC class.
A bolt. A bolt type holds its bolt, component.bolt, which every bolt of its groups is: its diameter, in mm; its grade, 4.6, 5.6, 8.8 or 10.9, and 8.8 where it gives none; its kind: bolt, a hex bolt with its head, where it gives none; anchor, an anchor bolt, a rod cast into concrete with a nut on top and an anchor plate at its foot; or rod, a threaded rod; its washers: under the head and the nut (2), under the nut (1, where it gives none) or none (0), and a rod's under both its nuts, or under the far one or its one nut; a rod's nuts: on both faces of the grip (2, where it gives none: through-bolted, or a base plate on levelling nuts), on the face at z = 0 only (1: into an anchor sleeve, or glued in) or none (0); and its finish, hdg hot-dip galvanized or black.
Reference: the type checks in validateManifest (src/core/model/model.ts), validateOpeningFamily (src/core/elements/openings.ts), validateFootingType (src/core/elements/footings.ts), validateInsertType (src/core/elements/inserts.ts).
Part of 0.2; OpenEik 0.1 had it as the proposal components. By the steward's decision of 26 October 2026 (open questions, 73), the families toilet and basin are deprecated (Part I, 9.6). A reader reads a component type of either family, and its elements, as 0.1 does. A writer SHOULD NOT write one: it writes a terminal instead (section 6.9), its type's terminal.kind wc for a toilet and washbasin for a basin, as the reference implementation turns them on load. A validator SHOULD warn about each such type (component-retired).
5.1 Layers
A layer is {id, name, function, material, thickness, color, core} with optional pattern, inset, extent and domain rules (framing, joists, precast).
functionis one ofstructure,substrate,insulation,finish,membrane.thicknessis in mm. Only amembraneMAY have thickness 0; the sum of a type's layer thicknesses MUST be positive.- Layer ids MUST be unique within the type.
coremarks the core layers. The layers before the first core layer are the exterior layers.inset(mm, 0–3000) is allowed only on slab and roof types;extent(where a roof layer stops in plan) only on roof types.- Order: wall layers exterior first, left of the directed baseline; horizontal layers top first (Part I, 5.1).
- When a type has layers, the element's thickness is the sum of the layer thicknesses, and the element's own
width(walls) orheight(horizontal elements) is ignored for its body (Part IV). thermal(optional) is{lambda?, air?, sd?}: the layer's own design thermal conductivity in W/(m·K), which a calculation uses instead of its material's (a framed layer's, say, or a product's);air, which makes the layer an air layer and says whether it isclosed,slightly-ventilatedorventilated(EN ISO 6946, 6.9; behind a ventilated air layer the layers outside it do not count); andsd, the water vapour diffusion-equivalent air layer thickness in m, from 0 to 100 000, of a membrane or foil (EN ISO 13788).
Reference: validateManifest (layer checks), basicSolids (thickness ?? e.width, thickness ?? e.height).
5.1.1 A layer's grain and an element's main direction
Part of 0.2. OpenEik 0.1 had it as the proposal grain: in a model of 0.1, read by 0.1's rules (Part I, 9.6, rule 3), grain and mainDirection are members a schema of 0.1 does not know, which a reader keeps (Part I, 10). The section adds these two members and no file.
By the steward's decision of 28 October 2026 (open questions, 90). A layer of cross-laminated timber (CLT), and any layer stiffer one way than the other, such as LVL with cross veneers, a glulam deck or a profiled sheet, has a grain: its stiffness, its strength, its deflection, its vibration and its fire resistance depend on which way its fibres run. These rules let a model say so, so that two tools that read one building read one layup.
- A layer's grain. A layer of a type of the category
slab,wall,roof,ceilingorfoundationMAY carrygrain:"along"where its fibres, or a sheet's strong direction, run along the element's main direction (rules 2 to 4), and"across"where they run square to it in the layer's plane. A layer withoutgrainstates none: it is isotropic, or its grain is not said.graintakes no other value, and no other angle. - A slab's, a ceiling's or a foundation's main direction is a direction in plan. Where the element has
panels(section 6.3), it runs square to theirdirection, as the panels do:(direction + 90) mod 180degrees, counter-clockwise from the model's x axis. Where it has nopanels, it MAY carrymainDirection, its main direction in degrees counter-clockwise in plan from the model's x axis. Where it carries both,mainDirectionMUST be(direction + 90) mod 180, the two compared modulo 180 within 0.01°: a validator reports one that is not (main-direction). Where it has neither, the model states no main direction for it, and its layers' grain is not placed. On a slab with a plane (section 6.3.1), its main direction is that direction in plan projected vertically onto the plane, as a roof'smainDirectionis (rule 4). - A wall's main direction is its
mainDirection:"vertical", up the wall, or"horizontal", along its baseline, in the wall's plane;"vertical"where it gives none. - A roof's main direction lies in the plane of each of its faces: along the fall line of the slope-defining edge whose plane the face is (Part IV, 4.4, rule 1), square to that edge in plan, unless the roof carries
mainDirection, degrees counter-clockwise in plan from the model's x axis, which every face takes, projected vertically onto its plane. A face of no slope lies level, and its main direction ismainDirection; without it, the model states none. - Which elements carry it. An element MUST NOT carry
mainDirectionunless its category isslab,ceiling,foundation,rooforwall: a number in degrees on the first four, and"vertical"or"horizontal"on a wall. A validator reportsmainDirectionon an element of another category (main-direction), and a value of the wrong kind as its schema's error. - The order of the layers is rule 6 of section 5.1: a horizontal type's top first, a wall's exterior first. So a reader knows which face each layer is on, and so where a layup is not symmetric.
- What it does not cover. A layer's lamella width, its edge gluing, a product's declared values and its European Technical Assessment are product data, which applications keep in their extension members (Part I, 11.2) until a later version has a product record. A layer's strength class is its material's
strengthClass(section 4.1), so a type whose layers are of two strength classes names two materials. - Bodies and prints. The grain and the main direction change no body: a compiler derives the same bodies with them or without them (Part IV), and the IFC4 print of Part VIII, 1 is the same until a later version says how IFC carries them.
A CLT floor type of five lamellas 40 mm thick, C24 along and C14 across, top first, has the layers {"function": "structure", "material": "CLT C24", "thickness": 40, "grain": "along"}, then "CLT C14" "across", "CLT C24" "along", "CLT C14" "across" and "CLT C24" "along", each with its id, name, colour and core. A floor of it whose panels, 2.4 m wide, lie side by side along y and span along x has "panels": {"width": 2400, "direction": 90}: its main direction is 0°, along x, and so are the fibres of its outer layers. A layup of seven layers with two along at each face, which no rule of alternation gives, is along, along, across, along, across, along, along. A wall over a wide opening whose outer layers run horizontally, so that it spans the opening as a beam does, has "mainDirection": "horizontal".
5.2 Sections
A section gives a member's cross-section: its shape, one of rectangle, I, T, RHS, CHS, round, L, 2L, U, sheet and custom, and its sizes. For a beam, width runs across the member and depth up; for a column, width runs along x and depth along y before the column's turn, the section's top towards +y. Except for a T, a 2L, a round and a custom section, which have only their own rules (rules 1 to 3, and 8 to 10), web < width and 2 × flange < depth MUST hold; an L section needs web < width and flange < depth; a sheet section's width and depth follow its profiled sheet (cover width and profile height).
A
Tsection is a flange on top of a web, which stands under the middle of the flange.widthis the flange's width,depththe overall depth,webthe web's thickness andflangethe flange's.web < widthandflange < depthMUST hold.A
2Lsection is two identical angles back to back: their vertical legs standgapapart, and their horizontal legs point outward at the top.widthis the overall width, both horizontal legs and the gap;depthis a vertical leg's length,weba vertical leg's thickness andflangea horizontal leg's. Each horizontal leg is(width − gap) / 2long.gap < width,web < (width − gap) / 2andflange < depthMUST hold. The angles' legs may be equal or unequal: a horizontal leg,(width − gap) / 2, need not be as long as a vertical one,depth.A
roundsection is a solid round bar:widthanddepthare both its diameter, and MUST be equal, within 10⁻⁶ mm. Itswebandflangeare not read, and no rule applies to them.gapis the distance between the backs of a2L's angles, in mm, from 0 to 10 000; absent, it is 0. A section of any other shape MUST NOT carry it.On a
T,radiusis the radius of its two root fillets, one each side of its web under its flange; on a2L, that of each angle's root fillet, where its vertical leg meets the underside of its horizontal leg. On anRHSit is the radius of its four outer corners, and its inner corners are rounded toradiusless the thicker of itswebandflange, square where that is not more than 0; without aradius, or with 0, all eight corners are square. On arectangleit rounds the four corners (rule 7). It is not read for aroundor acustomsection.designationnames the section as its product standard does, such asIPE 200,HEA 160orL 100 × 100 × 10, andgradethe grade of the members' material, such asS355J2,GL30corC24: plain strings (section 8, rule 3). A type can state a grade twice, in its section'sgradeand in thestrengthClassof the material itsmaterialnames (section 4.1). Where the section'sgradeis not empty, it is the members' grade: a reader that reads a member's grade MUST take it, and where the two differ a validator MAY warn (decided on 22 October 2026; open questions, 42).A
rectanglewith aradiusis a solid rectangle with its four corners rounded: each corner a quarter circle of that radius, tangent to the two sides that meet there, as a timber section with rounded corners is, such as wane-edged timber hewn flat on its faces so that the courses of a wall bear flat on each other. Without aradius, or with 0, its corners are square.radiusMUST NOT be more than half the smaller ofwidthanddepth, within 10⁻⁶ mm: at half, its two shorter sides are half circles, and a section as wide as it is deep is a circle. Its area iswidth × depth − (4 − π) × radius²and its centroid its middle; its area, its second moments of area and its members' volume and weight are the rounded shape's, its arcs exact. A command that writes a largerradiusis refused (Part V). A reader that reads a model holding one, without the whole-model check (Part III, 12), takes the section's corners as rounded to half its smaller side, and so does a compiler or a bridge that meets one.A
customsection is the region itsoutlinegives:outline.points, the contour of its outside, less each ofoutline.voids, each{points}, the contour of a hole through it. Acustomsection MUST carryoutline, and a section of any other shape MUST NOT. A contour is a list of entries in mm in the section's own plane,xrunning as the section'swidthdoes andyas itsdepthdoes: for a beam,xacross the member towards its left, seen from its start, andyup, before its roll; for a column,xandybefore itsturn. A contour is closed by its last side, from its last entry back to its first, and does not repeat its first point; it may run either way round. Each entry is one of:[x, y], a corner;[x, y, r], a corner rounded by an arc of radiusrmm, tangent to the two straight sides that meet there, each of which it takesr × tan(θ / 2)off,θbeing the angle through which the contour turns at the corner; withr0, the corner is square;{"through": [x, y]}, a point that the side from the entry before it to the entry after it passes through: that side is the arc of the circle through the three points.
A wane-edged log 200 mm wide and 250 mm deep, its corners rounded to 50 mm, is
{"points": [[0, 0, 50], [200, 0, 50], [200, 250, 50], [0, 250, 50]]}, the section that arectanglewith aradiusof 50 is too (rule 7); a D-log 150 mm wide and 200 mm deep, flat on its inner face, its top and its underside and round on its outer face, is{"points": [[0, 0], [150, 0, 100], [150, 200, 100], [0, 200]]}; glulam 90 mm × 315 mm with its edges chamfered 10 mm,{"points": [[10, 0], [80, 0], [90, 10], [90, 305], [80, 315], [10, 315], [0, 305], [0, 10]]}; and a round log 300 mm across, hewn flat and 240 mm wide on its underside,{"points": [[-120, 0], [120, 0], {"through": [0, 240]}]}, 300 mm wide and 240 mm deep. A void is written as the outline is: a bored core 40 mm across in the middle of the wane-edged log is{"points": [[80, 125], {"through": [100, 105]}, [120, 125], {"through": [100, 145]}]}.A
customsection's contours MUST each hold three entries or more, at least two of them corners, and no twothroughentries one after the other (the last entry and the first are one after the other). Within a contour:- no entry lies less than 0.1 mm from the entry before it, the first from the last, and no
throughentry lies within 0.01 mm of the straight line between the corners beside it; - a corner has a radius only where the contour turns, and both its sides are straight: neither the entry before it nor the one after it is a
through; - each straight side is long enough for the corners at its ends: what their radii take off it, together, is not more than its length, within 0.01 mm;
- no side crosses or touches another, the arcs of rounded corners and of
throughentries among them: two sides that follow one another share their one point and meet nowhere else.
Each void MUST lie inside the outline, with no side of it crossing or touching a side of the outline or of another void, and no void inside another. A
customsection'swidthanddepthMUST be the width and the height of its outline's bounding box, its arcs included, within 0.1 mm. Itsweb,flangeandradiusare not read, and no other rule of this section applies to them.- no entry lies less than 0.1 mm from the entry before it, the first from the last, and no
A
customsection is placed by the middle of its outline's bounding box, as every section is placed by the middle of itswidthanddepth(Part IV, 6.5): a point[px, py]of its outline liespx − mxacross a beam andpy − my + depth / 2up from its underside (Part IV, 6.2, rule 3), and(px − mx, py − my)from a column's centre before itsturn(Part IV, 6.1),(mx, my)being that middle. Its area, its centroid and its second moments of area are those of its region, its arcs exact and its voids taken out; its members' volume is that area along their length, and their weight that volume by their material's density (section 4.1). Plans and sections cut it as its region, its voids open, with its type's material and hatch, as they cut any section. A compiler MAY draw an arc as straight pieces: the arc is the rule, and the pieces are the compiler's, as a pipe's circle is (Part IV, 12.3, rule 5). Part VIII, 1.4 says how a bridge writes acustomsection and arectanglewith aradius.
Reference: validateMemberSection (src/core/elements/sectionRules.ts), which validateManifest calls for every type; partGrade (src/core/pieces/pieces.ts), which takes a section's grade before its type's material (rule 6); steelCells (src/core/geometry/steelProfiles.ts), an RHS's corners (rule 5). On the branch named above: rectangleRadius, roundedRectangleArea and roundedRectangleInertia (src/core/geometry/roundedRectangle.ts) and refuseRectangleRadius (src/core/elements/sectionRules.ts), rule 7.
5.3 Sizes a type sets
A door's or window's type with a windowFamily or openingFamily, a component type with a component (other than for a contour plate, a bolt group or a weld, which keep their own sizes), a round footing type and a cast-in item's type set their elements' width and height.
A beam whose type has a section takes its depth from the section: its height MUST equal section.depth.
No other type sets an element's width or height. A door or a window whose type has neither a windowFamily nor an openingFamily has its own width and height, whatever its type's are, and so has an element whose type is a void form or an edge detail (voidForm, edgeDetail).
- A writer MUST write such an element's
widthandheightequal to its type's (for a sectioned beam, itsheightequal to the section's depth). - A command that sets a different
widthorheighton such an element MUST be refused (Part V). An element file that says so fails the whole-model check (Part III, 12, rule 5): a validator MUST report it as an error, and a reader that performs the check refuses the folder (Part III, 14, rule 3).
Reference: typeSizes and typeSetSizes in src/core/model/typeSets.ts; refuseTypeSetSizes in run; typeSetInFiles in src/core/versions/eikFolder.ts.
5.4 Framing families and their expression language
A framing payload is a parametric 2D family, swept across its plane: {name, previewLength, parameters, parts} with optional trussStyle, edgeAnchor and tail. Its numbers are expressions: strings in the language below. This language is normative: every implementation that derives framing bodies MUST evaluate it exactly as stated.
Grammar (ISO 14977 EBNF; white space between tokens is ignored):
expression = sum ;
sum = product , { ( "+" | "-" ) , product } ;
product = unary , { ( "*" | "/" ) , unary } ;
unary = ( "+" | "-" ) , unary | primary ;
primary = number | call | name | "(" , sum , ")" ;
call = function , "(" , sum , { "," , sum } , ")" ;
function = "sqrt" | "abs" | "min" | "max" | "sin" | "cos" | "tan" | "atan" ;
number = digit , { digit } , [ "." , { digit } ] | "." , digit , { digit } ;
name = letter , { letter | digit | "_" } ;
letter = "A" | … | "Z" | "a" | … | "z" ;
digit = "0" | … | "9" ;
Tokens. A source is split into numbers, names and the characters ( ) + - * / ,. Any other character except white space makes the expression invalid. An expression is 1 to 240 characters and at most 160 tokens.
Names. A name not followed by ( is a value from the scope:
| Name | Value |
|---|---|
Length | the member's length in mm. For a beam: the length of its set-out line (Part IV, 6.2), hypot(plan length, endRise) |
| a family parameter | the element's framingParameters[name] if the parameter's scope is instance and the element gives it, else the parameter's value |
Overhang, TipTop | in a tail cut only: that tail's overhang, and the height of the tail tip's top over the bearing plane |
A name followed by ( MUST be one of the eight functions. An unknown name or function makes the expression invalid.
Functions. Angles are in degrees.
| Function | Arguments | Value |
|---|---|---|
sqrt(x) | 1 | √x; invalid when x < 0 |
abs(x) | 1 | |x| |
min(a, b, …), max(a, b, …) | 2 to 8 | the least or greatest argument |
sin(x), cos(x) | 1 | of x degrees |
tan(x) | 1 | of x degrees; invalid when |cos x| < 10⁻⁹ |
atan(x) | 1 | the angle in degrees whose tangent is x |
Evaluation. + - * / are IEEE 754 double operations, left to right within a precedence level; unary signs bind tighter than * and /. The expression is invalid when its value is not finite or its magnitude exceeds 1 000 000.
Parameters. A family has at most 32 parameters {name, value, scope, min, max}. A parameter's name matches ^[A-Za-z][A-Za-z0-9_]*$, is unique, is not Length and is not a function name. min ≤ max, and the value used (the type's, or the element's instance override) MUST lie in [min, max]. An element's framingParameters MAY name only parameters whose scope is instance.
The family plane of a beam: x runs along the member's set-out line from its start, z at right angles to it, upwards, from that line (the element's start point at level + offset, rising by endRise over the span; Part IV, 6.2). A family point (x, z) lies at plan position start + u (x cos α − z sin α) and elevation level + offset + z cos α + x sin α, where u is the unit plan direction and α the line's slope. Each part is swept across the plane by its width, centred on the plane.
Parts. A member part is a straight member from point a to b with a width and a depth; a profile part is a polygon outline with a width; a plate part is a convex nail plate on the members it lies on. when makes a part exist only while its value is greater than 0. cuts and cutBy cut a part by lines or by other parts. Part IV, 6.6, of 0.2, says exactly how: where each part lies and how it is cut, a tail's cuts and a slab edge element's plane, and what a family that cannot be built is.
Reference: framingSchema, framingExpression and framingProfiles in src/core/elements/framing.ts; the placement in src/core/geometry/framingGeometry.ts.
Example, from a rafter family in the reference implementation's examples: a profile part of width: "Width" whose outline runs from ["-Overhang", "-Rise*Overhang/Length"] through ["0", "0"], ["0", "Notch"], ["Seat", "Notch"] and ["Length", "Rise"] to ["Length", "Rise+Depth"], with parameters Width and Depth of scope type and Rise, Overhang, Seat and Notch of scope instance.
5.5 Building physics on types and rooms
A type MAY carry the values its elements have as a whole, declared by a manufacturer or a test, which a calculation uses instead of deriving them:
| Member | On | Meaning |
|---|---|---|
thermal.u | the layered categories, door, window | the thermal transmittance U in W/(m²·K), greater than 0, at most 20: of a door or a window as a whole, its frame included (EN ISO 10077); of a layered type tested as a whole, such as a prefabricated element, whose U replaces the one its layers give (EN ISO 6946) |
thermal.g | door, window | the total solar energy transmittance of the glazing, from 0 to 1 (EN 410) |
thermal.frameFraction | door, window | the share of the opening's area that is frame, from 0 to less than 1 |
thermal.lightTransmittance | door, window | the glazing's visible light transmittance τv, from 0 to 1 (EN 410) |
acoustic.rw | wall, slab, door | the weighted sound reduction index Rw in dB, from 0 to 120 (EN ISO 717-1) |
acoustic.lnw | slab | the weighted normalized impact sound pressure level Ln,w in dB, from 0 to 120 (EN ISO 717-2) |
- A type of a layered category carries
thermal.uonly, and a wall's or a door'sacousticcarriesrwonly. - A door's or a window's type SHOULD carry
thermal.u; one with glazing SHOULD carrythermal.gtoo. - An element's fire resistance class stays the fire profile's
fireClass(section 8), and a material's reaction to fire is itsfireReaction(section 4.1). - A roof window has the values of the
windowtype it names (section 6.3,roof.windows).
A room type's domain data, room (section 5), MAY also say:
heated: whether its rooms are heated, true for above 10 °C, as a heated floor area such as BBR's Atemp counts them;temperature: the rooms' design indoor temperature in °C, from −50 to 60;use: what the rooms are used for, a plain string of at most 80 characters (section 8, rule 3), such asresidential,officeor a code of a national list of uses.
5.6 Slab edge and gutter sections
By the steward's decision of 26 October 2026 (open questions, 74 and 75), so that Part IV, 4.6 and 4.7 derive these elements' bodies from the records alone.
A slab edge type's edgeProfile gives its section: its shape, a rectangle, an L or a U; its width and depth; an L's or a U's web, the thickness of its upstands, and flange, the thickness of its bottom leg (a rectangle carries both, and they mean nothing); its anchor, slabTop or structureBottom, the height its section hangs from; and, where it has them, a facing (a board of a material and a thickness on its outer face, as deep as the section or its own depth), a beam (a width and a depth to which it thickens its host under its edge) and a chamfer (a width and a height cut from its upstand's top inner corner). A gutter type's gutterProfile gives its section: a halfRound of an inner diameter, or a box of an inner width and depth, both thickness thick; and its horizontalOffset and verticalOffset, which its elements' own add to (section 6.3).
- An
L's or aU'sflangeMUST be less than itsdepth, and itsweb(aU's two webs together) less than itswidth, so that the section has an inside. - A
chamferMUST be on anLor aU, itswidthat most theweband itsheightat most thedepthless theflange: it is cut from the upstand, above the bottom leg. - A
halfRound'sgutterProfileMUST give itsdiameter, and abox's itswidthanddepth.
Reference: chamferProblem in src/core/elements/edgeChamfer.ts and the type checks in validateManifest (src/core/model/model.ts: "Profile web and flange must leave an open interior", "A half-round gutter needs a positive diameter", "A box gutter needs a positive width and depth").
6. Elements
An element is one placed thing of the building: a wall, a slab, a door. Every element has:
| Member | Meaning |
|---|---|
id, name | identity and display name (non-empty) |
category | one of the thirty-one categories (section 6.2) |
typeId | its type, of the same category |
levelId, offset | its level and the offset from it (Part I, section 4) |
height, width | positive, at most 100 000 mm; their meaning depends on the category |
profile | 1 to 500 plan points; its meaning depends on the category |
revision | Part I, section 8 |
Everything else is optional. The members of section 6.3 belong to the categories it lists; the others that the element schema names, declaredGeometry (section 12.1) among them, may be on any element, though most mean something for a few categories only (section 6.3 describes some).
An element or a type imported from IFC may carry ifcSource, {globalId, entity, units?, properties?}: the GlobalId and the IFC class it was imported from, the units of its numbers, and the property sets it was imported with, {<set name>: {<property name>: value}}, each value a text, a number or a truth value. units has one value, "specification": every number of properties is in this specification's units, a length in millimetres and an angle in degrees (Part I, 3), any other measure in its SI unit. A writer that imports a file SHOULD convert its numbers so and say so with units. Where units is absent, the record does not say which units its numbers are in, as records written before 29 October 2026 do not, and a reader does not convert them. A bridge keeps the GlobalId (Part VIII, 1, rule 3) and prints the property sets back, typed by IFC4's templates where IFC4 defines the set, a number of a measure with a unit only where units says which units it is in, and under a name that does not start with Pset_ where it does not (Part VIII, 1, rule 5, and 1.5). Reading IFC (Part VIII, 2) adds the predefined type and the user-defined type an object was read with (ifcSource.predefinedType, objectType), and shape: "given" on an element whose shape is the body its reader gave rather than its members.
6.1 Element rules every reader needs
- An element's
typeIdMUST name a type of the same category, and itslevelIda level. - A wall's and a beam's profile MUST be exactly two points at least 10 mm apart in plan.
- A slab's, ceiling's, roof's or shaft's profile MUST be an outline of three points or more, with an area of at least 100 mm², no two consecutive points less than 0.1 mm apart, and no edge crossing or touching another. Two edges that follow one another share a point, and meet there without touching in this rule's sense; they MUST NOT meet anywhere else, as they do where an outline turns back along itself. A foundation's profile is such an outline, or, for a round footing type, one point: the centre.
- A room's profile is one point (its boundary is found from the walls) or an outline of three points or more drawn by hand; never two points. A room MUST carry
roomwith itsnumber, unique on its level. Its boundary found from the walls, its ceiling and its quantities are 0.2's, in Part IV, 7.5. - A door or window MUST be hosted by a wall (
hostId). It MUST fit its host:along ≥ 0,along + width ≤the host's length,offset ≥ 0, and its topoffset + heightat most the host's height (or under the host's attached top where that rises higher). Where its top is over the host's height, each corner of its rectangle, or each point of its type's outline placed at the opening (Part IV, 4.3), MUST lie at or under the host's attached top at that point's distance along the host's centreline, the top that Part IV, 5.3, rules 4 and 5 derive. Two openings in one wall MUST NOT overlap. Two openings overlap when their shapes in the wall's elevation share an area: their rectangles, fromalongtoalong + widthand fromoffsettooffset + height, or, where a type gives an outline, that outline placed at its opening. Openings that only touch, along an edge or at a corner, do not overlap. - A slab edge element MUST be hosted (
hostId) by a slab or a foundation. A rebar element MUST be hosted by a slab, a foundation, a beam, a column or a slab edge element, and a mesh element by a slab, a foundation or a wall. A rebar element carriesreinforcementorbars; a mesh elementreinforcementorsheet. The rules that place reinforcement hold in its host's own frame, in a beam, a column or a slab edge element as in a slab. Where they name the host's thickness, a beam's, a column's or a slab edge element's is its section's depth across the plane the bars lie in. A slab edge element'shostEdgeIdMUST name an edge of its host's outline (rule 10), the edge it runs along (Part IV, 4.6); a round footing has none. Where slab edge elements thicken their host (Part IV, 4.6, rule 9), the thickened edges MUST fit it, as Part IV, 4.6, rule 11 says. - A stair's profile is two points (its start and a point up its first run, or for a circular stair its centre and its start), and it carries
stair. Its numbers and the layout of a straight, L or U stair are 0.2's, in Part IV, 7.3. - A component's profile is two distinct points (its insertion point and orientation) unless it is a cast-in item placed by
insertAt. - A room separator's and a property line's profile is two points or more.
- The outline's boundary edge ids (
edgeIds) of a slab, foundation, ceiling, roof or shaft, when present, MUST be unique and one per profile point. - A railing MUST meet the host and edge rules of section 12.2: it stands on a stair, on the outline of a slab or a shaft, or on a line of its own.
- A generic element's profile is one point, or two distinct points; it has no
hostId, and its shape is declared geometry, its own or its type's (section 6.6). - A gutter MUST be hosted (
hostId) by a roof, and itshostEdgeIdMUST name an edge of that roof's outline (rule 10), the edge it hangs on (Part IV, 4.7). Itsprofileis not used for placement.
The category schemas elements/<category>.schema.json encode the rules a schema can state (point counts, required members, members that do not belong to the category). The rest a validator checks in code.
Reference: validateElement in src/core/model/model.ts and the validators it calls; for rule 6's bar sets, validateBars and barHosts in src/core/elements/bars.ts.
6.2 The categories
| Category | Discipline folder | Profile | height, width | Notes |
|---|---|---|---|---|
wall | architecture | centreline, 2 points | height above the base; thickness from the type's layers, else width | top: section 6.4 |
slab | architecture | outline | thickness from layers, else height | top face at level + offset |
foundation | structure | outline, or 1 point (round footing) | as slab | |
ceiling | architecture | outline | as slab | |
roof | architecture | outline | as slab; pitched by roof | Part IV, 4.4 |
beam | structure | plan axis, 2 points | depth and width without a section; the section's otherwise | underside at the start |
column | structure | centre, first point | length; side of a square column without a section | base at level + offset |
door, window | architecture | not used for placement | the opening's size | hosted by a wall |
slabEdge | structure | not used for placement | the edge beam's size | hosted on a slab edge |
rebar, mesh | structure | as their payload says | bar or sheet sizes | hosted |
component | architecture or structure (Part III) | insertion point and orientation | from the type | plates, brackets, bolts, welds, cast-in items |
gutter | architecture | not used for placement | from the type | hosted on a roof edge (hostId, hostEdgeId) |
room, roomSeparator | architecture | point or outline; line | room height | no body |
shaft | architecture | outline | height to its top | opens the slabs, ceilings and roofs it passes, and a stair's shaft foundations too (Part IV, 4.2, rule 8); no body |
stair, railing | architecture | start and direction; line or host edges | from type and payload | derived runs and balusters |
pipe, duct, terminal | systems | run of points; a terminal's point, and the way it faces (section 6.9) | sizes from type and payload | a run's body: Part IV, 12; a component in a pipe or a duct is hosted on it (section 6.9) |
terrain, grading, propertyLine | site | points, outline, boundary | surfaces; no body | |
furniture, planting, road, parking, fire | architecture | point or line | from the type | |
generic | architecture, or the one its generic.discipline names | insertion point, or insertion point and orientation | not used: its shape is its declared geometry | a thing no other category fits; never hosted (section 6.6) |
A category that is not in this table is not one of 0.1's: an element or a type of such a category, one a later version adds, is kept as Part I, 10, rule 5 says. 0.2 adds member, a member between two points, which section 6.2.1 gives.
- A category MUST be a plain name: a lower-case ASCII letter, then ASCII letters and digits, at most 32 characters in all (
^[a-z][A-Za-z0-9]*$), and no device name of a common operating system,con,prn,aux,nul,com0tocom9orlpt0tolpt9, in any case. The thirty-one are such names, in lower camel case (slabEdge), and so is every category a later version adds.elements/element.schema.jsonandtypes/type.schema.jsonstate the rule, so a record whose category breaks it does not validate (Part III, 3, rule 2).
A category names a folder of a record's path (Part III, 4.2), and is not escaped (Part III, 2): rule 1 makes it a name that every common file system takes as it is written, as Part III, 2 makes a name of an id.
6.2.1 A member between two points
Part of 0.2. OpenEik 0.1 had it as the proposal member: in a model of 0.1, read by 0.1's rules (Part I, 9.6, rule 3), an element or a type of the category member is of a category 0.1 does not have, which a reader keeps (Part I, 10, rule 5). The section adds the category member and one member of its elements, end, and no file: its elements and types are records of Part III, 4's layout.
By the steward's decision of 30 October 2026 (open questions, 110), asked by an analysis application: one rule for linear members in any direction, and a category for what is neither a beam nor a column. A beam is set out on its underside and needs a run in plan (section 6.1, rule 2; Part IV, 6.2), and a column stands plumb on its base (Part IV, 6.1), so neither records a brace, a strut or a tie that runs steeply, or plumb, from one point to another. A member's record gives the two ends of the line through the middle of its section, and Part IV, 6.7 builds it as Part IV, 6 builds a beam.
- The category.
memberis a linear structural member that is neither a beam nor a column: a brace, a strut, a tie, a member of a truss or of a frame, a raking post. Its discipline folder isstructure(Part III, 4.1), and in the owners' layout it is structure's (Part III, 4.4, rule 2). Its type is of the categorymember. - Its type MAY carry a
section(section 5.2), as a beam's type does: itswidthruns across the member and itsdepthsquare to it, before the member's roll (Part IV, 6.7). It carries no other payload of section 5's table but those any type may carry; its schema sets each tofalse. - Its line. Its profile is two points in plan, its start and its end, which MAY be one point, so that the member stands plumb. Its start is its profile's first point at
elev(levelId) + offset, and its end its second point atelev(end.levelId) + end.offset: it MUST carryend,{levelId, offset}, whoselevelIdMUST name a level of the model (Part I, 7). The two points lie on the member's reference line, the line through the middle of its section (Part IV, 6.5), and MUST be at least 10 mm apart in space (member-length). - Plumb. A member is plumb where its two plan points lie within 10⁻⁶ mm of each other. A writer SHOULD write a plumb member's two plan points equal, and a validator SHOULD warn of a member whose plan points lie less than 1 mm apart but not within 10⁻⁶ mm (
member-plumb): its section turns with the direction from one to the other (Part IV, 6.7, rule 2), which so short a run in plan hardly sets. - Its size. With a section, the section sizes the member (Part IV, 6.3): its
heightMUST equalsection.depth, as a sectioned beam's does (section 5.3), and itswidthis not read. Without a section, its section is a rectanglewidthacross andheightdeep. - Its members. It MAY carry
roll,taperandjoins, which mean for it what they mean for a beam (section 6.3; Part IV, 6.4 and 6.7); a taper needs a rectangular section, as a beam's does. It MUST NOT carryendRise,turn,base,connectionor another member that section 6.3 gives other categories: its schema sets each tofalse. - What its record does not say. A member's record says where it is and what its section is. How its ends are supported, released or connected in an analysis is no member of it: an application keeps that in its own records, or in extension members of its own (Part I, 11.2), which a member carries as a beam does. Its
joinssay only where its body is cut (Part IV, 6.4). - One element for one piece. A beam and a column keep their records and their meaning: a beam with an
endRiseand a column are read as in 0.1, and Part IV, 6.7, rule 9 reads either's reference line as a member's line. A writer writes each linear piece as one element, a beam, a column or a member, and never as two. Which is its choice: a beam is set out by its underside, a column stands on its base, and a member is set out by the middle of its section, in any direction. - Commands. A command processor makes and changes a member and its type as any element and type (Part V, 1, rule 5), holding each to this section's schemas. It refuses an
endwhoselevelIdnames no level (rule 3), and aheightother than its type's section's depth (rule 5), as it refuses a top constraint's level and a beam's height. A member'sendon a level reaches to it as a top constraint does:level.deleteis refused while one does, unlessmoveTonames the level they move to, and the end moves to it keeping its height (Part V, 5, rule 4).
A brace of a square hollow section 100 × 100 × 5 from the foot of a column at [0, 0] on level 0, elevation 0, up to [6000, 0] 150 mm under level 1, elevation 3600, is {"category": "member", "profile": [[0, 0], [6000, 0]], "levelId": "level-0", "offset": 0, "end": {"levelId": "level-1", "offset": -150}, "width": 100, "height": 100, …}, its type {"category": "member", "section": {"shape": "RHS", "width": 100, "depth": 100, "web": 5, "flange": 5, "designation": "SHS 100×100×5", "grade": "S355"}, …}: its line runs from (0, 0, 0) to (6000, 0, 3450), through the middle of its section. A hanger plumb from [2000, 1000] at level 1 down to 900 mm under it has the profile [[2000, 1000], [2000, 1000]], the offset 0 and the end {"levelId": "level-1", "offset": -900}.
6.3 Members that belong to some categories
An element MUST NOT carry these members unless its category is listed. The element category schemas set each forbidden member to false.
| Member | Categories | Meaning |
|---|---|---|
top | wall, shaft, stair | a wall's top constraint and attachment (section 6.4); a shaft's or stair's top is only a constraint |
wallOutline, edges, framingTop, framingJoints, framingCorners, framingStuds, framingTees, framingStart, framingOffset | wall | an elevation outline, edge details, timber framing rules (laid out by Part IV, 7.4) |
roomBounding | wall, column | false when the element does not bound rooms |
turn | column | turn about its centre (its reference line, Part IV, 6.5) in degrees, counter-clockwise in plan |
base | column | base attachment (Part IV, 5.2) |
roll, endRise, taper | beam; roll and taper on a member too (section 6.2.1) | roll about the reference line (Part IV, 6.5); rise of the end over the start; a linearly varying depth |
connection, joins | beam, column; joins on a member too (section 6.2.1) | a schematic end plate; member joins (Part IV, 6.4) |
bottomPlate | door, window | whether a framed wall's bottom plate runs through |
roof | roof | slope-defining edges, overhangs, roof windows, the roofs it joins (joinGroup, below) |
joints, panels | slab, foundation, ceiling | movement joints, panel division |
edgeAttachments | slab, foundation, ceiling, roof | edges of the outline trimmed to a wall's face (section 6.7) |
room | room | number, name, department, unit, finishes |
stair, railing | stair, railing | shape and own numbers |
mep | pipe, duct | heights, size, system and insulation (section 6.9) |
terminal | terminal | its flow and its heat (section 6.9) |
bars | rebar | a bar set |
sheet | mesh | mesh sheets |
terrain, grading, propertyLine | their categories | points, pads, setbacks |
generic | generic | what the element stands for, its IFC class and its discipline, where they differ from its type's (section 6.6) |
notches | slabEdge | stretches where its outside upstand is cut down; of 0.2 (Part IV, 4.6, rules 12 to 14), and in 0.1 a member the schemas do not know |
A panel division. panels, on a slab, a foundation or a ceiling, is {width, direction?, start?, prefix?}: a rule that divides the element into strips width mm wide (100 to 10 000), which a plan draws and numbers and a schedule counts. It is no geometry, and changes no body. The strips lie side by side along direction, in degrees counter-clockwise in plan from the model's x axis, 0 where it is absent: their widths add up along that direction from the point of the outline least far along it, moved on by start mm (0 where it is absent), and the lines between them run square to it. Each strip is labelled prefix (P where it is absent) followed by its number, counted from 1 along direction. So a floor of panels laid side by side along y, each spanning along x, has the direction 90.
Some members may be on any element, and mean something for a few categories only. Four of them, two members of the roof payload and the terrain payload's points mean this:
componentInverted, on acomponent:truehangs its body down from its insertion height, fromz − heighttoz, where it otherwise stands up from it, fromztoz + height(zis its level's elevation plus itsoffset). It changes nothing for a component placed upright, by axes of its own or as a cast-in item.axes, on acomponent:{x, y}, two vectors in the model's axes,xnot zero andynot parallel to it. They are the component's own frame, and take the place of its orientation andupright. Its x isxmade a unit vector, its y isymade square to x and a unit vector, and its z is x × y, or y × x where the component isflipped. The frame's origin is the insertion point, the profile's first point, at its level's elevation plus itsoffset. A plate lies in its x–y plane: its outline is in x and y, and its thickness, the element'sheight, runs along z from the face, from 0 toheight. A bolt group's bolts run along z, and a weld along x. Withaxes, the profile's second point, which rule 8 of section 6.1 still asks for, orients nothing, andcomponentInvertedchanges nothing.miterEnds, on aslabEdge:truemitres both its ends where its host's outline turns, so that it meets the edge element round the corner on the corner's bisector, andfalsekeeps both ends square. Without it, an end is mitred where the edge round that corner carries an edge element that mitres by itself, one whosemiterEndsis notfalseand whose type is no framing family (section 5.4), and where its own type is no framing family either. Part IV, 4.6, rule 6 says where a mitre is cut, and where an end stays square all the same.horizontalOffset, on aslabEdgeor agutter, in mm: moves its section square to its host's edge, a slab edge's in from the edge, into the host's outline, and a gutter's out from its roof's edge, added to its type'sgutterProfile.horizontalOffset. A negative value moves it the other way.verticalOffset, on either, raises its section, a gutter's added to its type'sgutterProfile.verticalOffset(Part IV, 4.6, rule 4, and 4.7, rule 4).terrain.points, on aterrain: points in plan with a height,[x, y, z], z above its level's elevation plus itsoffset. Between them, the ground is the Delaunay triangulation of the points in plan, clipped to the element's outline (itsprofile): a triangulated irregular network, as LandXML's surfaces and IFC'sIfcTriangulatedIrregularNetworkare. Where four or more points lie on one circle, any of the triangulations is the surface. Where two terrains overlap, which ground is on top is not defined in 0.1, since the order of elements has no meaning (Part III, 9, rule 3); a writer that wants one ground there clips the other terrain's outline.roof.windows, on aroof: its roof windows, each{id, edgeId, center, width, length, openingOnly?, reveal?, typeId?}. A roof window lies on the face of the edgeedgeIdnames (Part IV, 4.4), centred overcenterin plan,widthacross the slope andlengthalong it.openingOnlymakes it an opening with no window in it, andrevealsays how the opening runs through the roof. A covering and the infill under it that cut one opening carry the same windowid.typeId, by the steward's decision of 21 October 2026, names the window's type: its product, and its U, g, frame fraction and light transmittance (section 5.5). It MUST name a type of the categorywindowwhere it names a type of the model, and SHOULD name a type of the model (Part I, 7, rule 3). It belongs on the entry that holds the window, not on anopeningOnlyone.roof.joinGroup, on aroof: a name that the roofs of one group share. Roofs of one group join: where another roof of the group lies over a face, that part of the face is cut away, and a gutter along an edge that lies under another roof of the group is left out there.
A plate, a bolt group and a weld, components of a type of the family plate, bolt or weld (section 5), carry their own data in three members:
plate, on a plate: its own shape over its type's. Itsoutline, three or more points in its own x and y in mm, around its insertion point, makes it a contour plate of that outline in place of the rectangle its type gives, and itsholes, each as a plate type's hole is (section 5), go through it beside its type's. The holes of the bolts through it come with their bolt group.bolts, on a bolt group: its bolts, each the bolt its type holds (section 5), all along its z.positionsare their centres in its x and y, in mm.gripis how far they pass through the parts along its z, from the face the head, or an anchor bolt's nut, bears on, at z = 0, to the face the nut bears on.throughnames the elements they pass through, each drilled for them, plates and members.lengthis a bolt's length from under its head,holethe holes' diameter, andembedan anchor bolt's reach past the grip into the concrete, or a rod's past the grip, its far nut included. Where a group gives nolength,holeorembed, the reference implementation works them out from tables of ISO bolts and hole clearances that no record holds (open questions, 73).weld, on a weld: a fillet weld, its root along its x for itswidth, its length, and its legs along its y and z.throatis its throat, a, in mm, and its legs a·√2. Itskindisfillet, the one kind of 0.1, where it gives none.siteistruefor a weld made on site rather than in the shop, andpartsnames the one or two elements it joins.
What componentInverted, axes, plate, bolts, weld and roof.joinGroup do to a roof's or a component's body is no class-A rule (Part IV, 2): how a compiler derives it is reference behaviour in 0.1, and a component's frame, a plate, a weld's fillet and each bolt's shank become rules in 0.2 (open questions, 73 and 99), which Part IV, 7.6 gives. What miterEnds, horizontalOffset and verticalOffset do to a slab edge element's or a gutter's body, and where a roof of its group buries a gutter, are class-A rules since 26 October 2026 (Part IV, 4.6 and 4.7; open questions, 74 and 75).
Reference: validateElement, validateSlabJoints, validateSlabPanels and slabPanels (src/core/elements/slabMarks.ts), validateRoof (roofs.ts), validateBars (bars.ts), validateSheet (meshSheets.ts), validateSiteElement (src/core/site/siteElements.ts), validateMemberJoins (memberJoins.ts), validateWallEdges (edgeDetails.ts), validatePlateType and validatePlateShape (components.ts), boltSpecSchema and validateBoltGroup (bolts.ts), validateWeld (welds.ts); for the four members above, plateFrame (components.ts), edgePlacement (edgePlacement.ts), gutterSolids and unburiedSegments (gutters.ts) and roofSolids (roofs.ts).
6.3.1 A slab on a sloped plane
Part of 0.2. OpenEik 0.1 had it as the proposal slopedSlab: in a model of 0.1, read by 0.1's rules (Part I, 9.6, rule 3), plane is a member a schema of 0.1 does not know, which a reader keeps (Part I, 10), and the slab is level. The section adds this one member and no file.
By the steward's decision of 30 October 2026 (open questions, 111), asked by an analysis application: a slab may lie on a sloped plane, as a ramp, a sloped floor or deck, or a plate of an analysis model does. Its plane is given as a roof's slope-defining edge gives one, and Part IV, 4.2.1 builds it by the plane rule of a pitched roof (Part IV, 4.4), so that roofs and sloped slabs share one plane rule and one quantity rule.
The plane. A slab MAY carry
plane, the plane of its top face. It gives the plane's gradient one way and its direction one way:- its gradient as
slope, in degrees from 0 to 75, as a roof edge's slope is (section 6.3); or asriseoverrun, both in mm,runmore than 0, its slope atan(rise/run), which MUST NOT be more than 75 degrees; - its direction as
edgeId, an edge of the slab's outline (Part I, 6, rule 6; section 6.1, rule 10), from whose line its top rises into the outline, as a roof's top rises from a slope-defining edge (Part IV, 4.4, rule 1); or asfall, the direction in plan in which its top falls, in degrees counter-clockwise from the model's x axis.
It carries exactly one of
slopeandrisewithrun, and exactly one ofedgeIdandfall.- its gradient as
Where it lies. The slab's
elev(levelId) + offset, z1, is its top's height along the line of the edgeedgeIdnames, or at its profile's first point where it givesfall. With σ its slope, its top at a point p in plan is z(p) = z1 + tan σ · (n · (p − a)), where a is the edge's start and n its unit normal into the outline, or z(p) = z1 − tan σ · (f · (p − p0)), where f = (cosfall, sinfall) and p0 is the profile's first point.Either form is one plane. Each gives the plane's slope, the direction in plan in which its top falls, −n or f, and its top's height at the profile's first point, z(p0). A reader derives these from either form, and so either form from the other where it can be written: an edge form where the outline has an edge square to the fall.
Its top face. The plane is the slab's top face, as a level slab's top is
elev(levelId) + offset(Part I, 4) and a pitched roof's planes are its top (Part IV, 4.4). Its thickness, its type's layers' total or else itsheight(Part IV, 4.2, rule 1), is measured square to the plane, as a roof's is (Part IV, 4.4, rule 4), and its layers lie under it, top first.A level slab has no
plane, or one of slope 0: its top is z1 everywhere, and nothing of it changes.Which slabs. Only a slab carries
plane. A validator reportsplaneon an element of another category, anedgeIdthat names no edge of the outline, and ariseoverrunsteeper than 75 degrees (slab-plane). A slab whose plane slopes, of a slope over 0, MUST NOT host a slab edge element in 0.2 (slab-plane-edge; Part IV, 4.2.1, rule 6).Its grain. A sloped slab's main direction (section 5.1.1), from its panels'
directionor itsmainDirection, is a direction in plan projected vertically onto its plane, as a roof'smainDirectionis (section 5.1.1, rule 4). A panel division (section 6.3) stays one in plan.
A ramp 6000 mm long and 2000 mm wide, [[0, 0], [6000, 0], [6000, 2000], [0, 2000]] on level 0, elevation 0, with the offset 0, rising 300 mm from its west edge, its fourth, ramp-a:edge:3, to its east edge, has "plane": {"edgeId": "ramp-a:edge:3", "rise": 300, "run": 6000}: its top is z = x/20, from 0 at x = 0 to 300 at x = 6000. The same plane by its fall is {"fall": 180, "rise": 300, "run": 6000}, since the profile's first point lies on the low edge. A triangular landing whose fall runs square to none of its edges has only the second form.
6.4 A wall's top
top is {constraint, attach?, extendExteriorLayers?, cutRoofId?, cutRoofFace?}:
constraintis"unconnected"(the top isbase + height) or{levelId, offset}(the top is that level's elevation plusoffset, which MUST lie above the base).attachis{hostId, face, offset?, mode?}: the wall's top conforms to a face of a roof, floor, foundation or ceiling: its"underside", its"top", or{layerId}, the underside of one of the host's layers.modeis"raking"(the default: the top follows the face) or"level"(flat at the lowest point of the face over the wall's core).heightandwallOutlinekeep their unconnected values while a wall is attached.
The derivation is in Part IV, section 5.3.
Writers MUST NOT write the legacy members topRoofId, topCeilingId and roofCutId. A reader SHOULD read them as top (topRoofId and topCeilingId as an attachment to that host's underside, roofCutId as cutRoofId).
Reference: wallTopSchema, legacyWallTop in src/core/elements/wallTop.ts; normalizeElement in src/core/elements/edges.ts folds the legacy members into top on load; run refuses them in patches.
6.5 Hosted openings
A door or window names its wall in hostId. along is the distance in plan from the wall's first profile point to the opening's near edge; width and height are its size; offset is the height of its bottom above the wall's base. flipped turns it to face its wall's interior rather than its exterior (section 6.8), and handFlipped mirrors its handing, and the shape its type's outline gives it, along its wall (Part IV, 4.3).
How it opens. By the steward's decision of 26 October 2026 (open questions, 71), as the reference implementation reads these members. A door's or a window's type with an openingFamily (section 5) says how its leaves or its lights open: operable whether they open, hinge the side they hinge on, swing the side they open to, and, for a door, operation how a leaf moves. With the element's flipped and handFlipped:
- The hinge side. A leaf or a light hinges at the end of its opening nearer its wall's first point, its start, at
along, wherehingeisleft, and at its other end, atalong + width, where it isright;handFlippedswaps the two.topandbottomhinge a window's light at its head or its sill, whateverhandFlippedsays. - The side it opens to. It opens to its wall's exterior, the left of the wall's baseline (Part I, 5.1), where
swingisoutward, and to its interior whereswingisinward;flippedswaps the two. - Several leaves or lights. A door of the kind
doorhaslightsXleaves side by side, and one of the kindgarageSideHingeditspanels. Ofnleaves counted from the opening's start, leafi(from 0) hinges at the start wherei < n/2and at the end otherwise, whateverhingeandhandFlippedsay. A window's lights stand in its grid,lightsXacross andlightsYup, or as itsmullionsdivide it; where they hinge at a side and stand in more than one column, columniofnhinges at the start wherei < n/2and at the end otherwise. - How a door's leaf moves, its
operation, on a family of the kinddoor:swing, or none, turns it on its hinges to the side it opens to.slideruns it along its wall: a single leaf hangs on the face of the wall on the side it opens to and travels its own width towards its hinge side; of several leaves, counted from the hinge side, the first stays, the second slides over it towards the hinge side, the third stays, and so on, on two tracks 6 mm apart, each leaf that slides on the track on the side the door opens to.pocketslides a leaf into the wall on its hinge side, and parts several leaves, each into the wall at the end of its own half (rule 3). - A family that does not open. Where
operableisfalse, its leaves and its lights do not open: rules 1 to 4 say nothing of it. - A family of the kind
doororgarageSideHingedSHOULD hingeleftorright: one that hinges at itstoporbottomhas no operation in 0.1.operationSHOULD beslideorpocketonly on a family of the kinddoor, and a reader ignores it on another. A validator SHOULD warn of both.
A garage door of the kind garageSectional runs up in its sections, one of the kind garageRoller rolls up, and one of the kind garageFolding folds its panels to both ends; hinge and operation say nothing of them. Part VIII, 1.2 maps each operation to IFC4's. The frame, the leaves or sashes and the glass become class-A bodies in 0.2 (Part IV, 4.3 and 4.3.1); a body drawn for a print, a clash check or a quantity is then closed, open, which the element schema allows, being a pose for showing.
Reference: openingSolids (hinge, swingToward) and pocketSide in src/core/elements/openings.ts; slidingLeaves, leafSlides and slideSide in src/core/elements/slidingDoors.ts; lightSpans in src/core/elements/mullions.ts.
6.6 Generic elements
The category generic is for a thing that no other category fits: a piece of equipment, a lift, a sculpture, signage, temporary works, a scanned part of an existing building. It is a disciplined way out: a thing that a category fits is modelled in that category, and nothing is made to look like something else, a box component or a piece of furniture standing in for a lift.
What it stands for. A generic type MUST carry the payload
generic,{standsFor, ifcClass?, discipline?}:standsFor, required: a non-empty text that says what the thing is (passenger lift,sculpture,scaffold tower);ifcClass: the IFC entity a bridge exports it as, written as IFC writes it (IfcTransportElement); absent,IfcBuildingElementProxy;discipline: the discipline folder it goes in, one ofarchitecture,structure,systemsandsite(Part III, 4.1); absent,architecture.
A generic element MAY carry
generictoo, with any of the three members: each member it gives wins over its type's.Its shape is declared geometry, and nothing else: its type's declaration, in the frame of a category placed at a point, its own, or both, under the rules of section 12.1. A generic element MUST have declared geometry, its own or its type's, so it has at least one body, and its declaration is authoritative for its
envelope. OpenEik defines no other geometry for it.Its placement. Its
profileis its insertion point, or its insertion point and a second, distinct point that gives its orientation, as a component's (section 6.1, rule 8); with one point, its x axis is the project's.elev(levelId) + offsetis its base, z = 0 of its frame (Part I, 4). Itswidthandheightare not used for its shape.Not hosted, cutting nothing. A generic element has no
hostId, and in 0.1 it cuts no other element.A category that fits comes first. Writers and agents SHOULD use a category that fits before
generic. A validator MAY warn when a generic element looks like an element of a category that fits (as the model-quality warnings of Conformance, 2 do for other categories), and an agent host SHOULD say how many of a model's elements are generic.Its size. A record's declared geometry SHOULD hold fewer than 10 000 faces in all, counting each face of a polyhedron or a mesh, n + 2 for a prism of n points, and 3 for a cylinder or a rod. Larger meshes, kept as binary assets beside the records, are planned and are not part of 0.1.
Promotion. When a category comes to fit (a later version adds one, or the thing is understood), the element moves to it by a batch of a
deleteand acreatewith the same id (Part V, 7): each command sees the model as the one before it left it, so the id is kept and no other command kind is needed. As any delete does, thedeleteremoves what depends on the element (Part V, 5).From 0.2 a generic type or element MAY also carry classification references (section 11).
A person. A figure of a person placed in a model, to show its scale or to check the free height over a place, is a
genericelement whose type stands for a person: the type'sgeneric.standsForisperson, and its shape is declared geometry (rule 2), a body as tall as the person it stands for. There is no categoryperson(decided on 30 October 2026; open questions, section 4, D9). How an application draws such a figure, a model of a body or a pose, is its own, in an extension member (Part I, 11.2).
A generic type standing for a passenger lift, and an element of it (compacted; on disk each member is a line):
{
"category": "generic", "color": "#8a9199", "height": 2600, "id": "type-lift-8",
"material": "Steel", "name": "Passenger lift, 8 persons", "width": 1600,
"declaredGeometry": {
"authoritativeFor": ["envelope", "clearances"],
"clearances": [{"body": {"bottom": 0, "kind": "prism", "profile": [[0, -1500], [1600, -1500], [1600, 0], [0, 0]], "top": 2100}, "id": "landing", "purpose": "operation"}],
"envelope": [{"bottom": -1200, "kind": "prism", "profile": [[0, 0], [1600, 0], [1600, 2100], [0, 2100]], "top": 3500}],
"level": "interface",
"tolerances": {"default": 10}
},
"generic": {"discipline": "systems", "ifcClass": "IfcTransportElement", "standsFor": "passenger lift"}
}
{
"category": "generic", "height": 2600, "id": "lift-a", "levelId": "level-0", "name": "Lift A",
"offset": 0, "profile": [[4000, 2000], [4000, 3000]], "revision": 0, "typeId": "type-lift-8", "width": 1600
}
The element stands at [4000, 2000] on level 0, its x axis pointing along +y; the type's envelope reaches 1200 mm into the pit below its base, and the landing in front of its doors must stay free. The type goes in types/systems/generic/type-lift-8.json, the element in systems/level-0/generic/lift-a.json.
6.7 Outline edges trimmed to a wall's face
edgeAttachments is a list of {edgeId, hostId, face}. Each entry trims an edge of a slab's, foundation's, ceiling's or roof's outline to a face of a wall:
edgeIdnames the edge. Edgenruns from the outline's pointnto the next; it is named byedgeIds[n], or<id>:edge:<n>where the element has noedgeIds(Part I, 6.6).hostIdnames the wall.faceis"interior"or"exterior": the exterior face is on the left of the wall's directed baseline (Part I, 5.1), the interior face on its right.
The outline stays as it is recorded. The trim is derived (Part IV, 4.5), so the edge follows the wall when the wall moves, turns or changes thickness, and neither record changes.
- Each
edgeIdMUST name an edge of the element's outline, and an edge MUST NOT be named twice. A round footing (section 6.1, rule 3) has no edges to name. hostIdMUST name a wall.- The edge MUST be parallel to the wall's baseline within 5°.
- Each end of the edge MUST lie no more than 1 mm beyond the face, on the side away from the wall. An attachment trims an edge back to the face; it never moves an edge out to meet it.
- The outline trimmed at every face its attachments name (Part IV, 4.5) MUST keep an area of at least 100 mm², as an outline must (section 6.1, rule 3).
A ground slab whose south edge is trimmed to the interior face of the south wall (compacted):
{
"category": "slab", "edgeAttachments": [{"edgeId": "slab-ground:edge:0", "face": "interior", "hostId": "wall-south"}],
"height": 250, "id": "slab-ground", "levelId": "level-0", "name": "Ground floor", "offset": 0,
"profile": [[0, 0], [10000, 0], [10000, 7000], [0, 7000]], "revision": 1, "typeId": "type-slab-250", "width": 250
}
The wall runs from [10000, 0] to [0, 0], so its interior face is on its right, the north side; its type is 300 mm thick, so the face is the line y = 150. The slab's edge 0, from [0, 0] to [10000, 0], lies on the wall's centreline. The slab's bodies start at the face and measure 10 m by 6.85 m in plan. A wall 400 mm thick moves the face to y = 200, and one 200 mm thick to y = 100; the slab follows, and neither record changes.
Reference: edgeAttachmentSchema, validateEdgeAttachments and footprintTrims in src/core/elements/wallTop.ts; validateFooting in src/core/elements/footings.ts; the edge.attach and wall.flip branches of run in src/core/model/store.ts.
6.8 Which way an element faces
By the steward's decision of 21 October 2026. An energy balance, a daylight study or a sun study sums walls, doors and windows by the way they face: their facing, a direction in plan, and its bearing, that direction's angle from true north.
- A wall faces its exterior: the left of its directed baseline (Part I, 5.1). Its facing is its left normal
n = (−u_y, u_x), whereuis the baseline's direction (Part IV, 3). - A door or a window faces its host wall's exterior,
n. Withflipped: trueit faces the wall's interior,−n. - A roof window faces down the face it lies on, the plane of the edge
edgeIdnames (Part IV, 4.4, rule 1). Its facing is that edge's normal out of the roof's outline,−n_i, and its tilt is the edge's slopeσ_i. Where that edge defines no slope, the window lies level: its tilt is 0, it faces straight up, and it has no bearing. - A facing
fhas the bearing(atan2(f_x, f_y) · 180/π − trueNorth) mod 360: its angle in degrees, from 0 to less than 360, clockwise from true north, wheretrueNorthis the project'ssite.trueNorth, true north's angle clockwise from plan +Y (section 2). - Without
site.trueNorth, plan +Y is north: bearings are taken withtrueNorth0. A validator SHOULD warn when such a model holds a door, a window or a roof window, whose bearings then rest on it.
In the one-storey house, the south wall runs from [10000, 0] to [0, 0]: its facing is (0, −1), south in plan. Its site gives trueNorth 15, so the wall's bearing is 180 − 15 = 165°, and so is the bearing of each of its windows that is not flipped.
Reference: exteriorFacing = !e.flipped in src/core/elements/openings.ts; facadeInWalls in src/core/elements/wallFacing.ts; roofFaces in src/core/elements/roofs.ts.
6.9 Heating, ventilation and plumbing
By the steward's decisions of 23 and 24 October 2026, from the reference implementation's plan 606 (open questions 45 to 51). Pipes, ducts and terminals (section 6.2) are the building services of a model. Their systems, a run's insulation, a heating terminal's heat and the components in a pipe or a duct are data of their records; their views and drawings are section 13's, and their bodies Part IV, 12's.
Systems. A run's mep.system, a type's pipe.system, duct.system and terminal.system, and the system of a terminal type's connection or outlet are systems of one enumeration:
| System | What it carries | Falls by gravity | Carries air |
|---|---|---|---|
sewage | waste water | yes | no |
storm | storm water | yes | no |
greaseWaste | waste water that carries grease, from a kitchen | yes | no |
oilWaste | waste water that carries oil, from a garage or a workshop | yes | no |
coldWater | domestic cold water | no | no |
hotWater | domestic hot water | no | no |
hotWaterCirculation | domestic hot water's circulation | no | no |
heating | heating water | no | no |
districtHeating | the primary water of district heating, supply and return as one system | no | no |
brine | brine, for cooling or a heat pump's collector | no | no |
compressedAir | compressed air | no | no |
gas | fuel gas | no | no |
supplyAir | supply air | no | yes |
extractAir | extract air | no | yes |
outdoorAir | outdoor air | no | yes |
exhaustAir | exhaust air | no | yes |
kitchenExhaust | a kitchen hood's exhaust | no | yes |
A run's mep.number, 1 to 99 and 1 when absent, is its system's number on the drawings: the heating system 20, which Swedish drawings write VS20. A system's code on drawings (KV for cold water, VS for heating, L for compressed air), its name and its colour are not data of the standard (section 8, rule 3): an application gives them, and a project may give its own in its standards, an application value (section 9.2). Whether a system falls by gravity, or carries air, is the system's, as the table says.
Insulation. A run's insulation is a code that a drawing writes after the run's size, and a thickness in mm that its body takes (Part IV, 12.1, rule 3). A pipe type and a duct type give them alike:
| Member | Meaning |
|---|---|
pipe.insulationCode, duct.insulationCode | the type's insulation code, 1 to 12 characters, a national value: R5DF40-C on a Swedish pipe drawing (class R5, hanging D, material F, 40 mm, surface C), B11 for a duct's fire insulation of class EI15 |
pipe.insulation, duct.insulation | the insulation's thickness in mm, from 0 to 200 |
A run's own mep.insulation gives its own, where it differs from its type's, each member optional:
| Member | Meaning |
|---|---|
code | its insulation code, as a type's |
thickness | its insulation's thickness in mm, from 0 to 200, beside its own code |
none | true: the run has no insulation, whatever its type gives |
bti | deprecated (rule 4): a pipe's code by its parts |
A run's insulation code is its own code, else its type's insulationCode; its thickness its own thickness, else its type's insulation, and 0 without either; with none it has none. What a code means, its kind, its text and a thickness, is the project's legend, an application value: a run's thickness is the model's, never only a code table's.
A code by its parts, deprecated. The reference implementation writes a pipe's code by the parts of one national code, a type's pipe.bti and a run's mep.insulation.bti: {class, hanging, material, thickness, surface?}, each part 1 to 8 characters and a national value, the thickness in mm from 1 to 200. {"class": "R5", "hanging": "D", "material": "F", "surface": "C", "thickness": 40} is the code R5DF40-C and 40 mm. 0.1 reads it, deprecated (Part I, 9.6): rule 4.
The heating pipe of this section's examples, a copper pipe on level 0, 22 mm, in the heating system 20, insulated with 30 mm of the code R4SF30:
{
"category": "pipe",
"height": 22,
"id": "pipe-heating",
"levelId": "level-0",
"mep": {
"insulation": {
"code": "R4SF30",
"thickness": 30
},
"number": 20,
"size": 22,
"system": "heating",
"z": [2400, 2400, 2400]
},
"name": "Heating supply",
"offset": 0,
"profile": [
[1000, 1000],
[5000, 1000],
[5000, 4000]
],
"revision": 0,
"typeId": "type-pipe-heating-cu",
"width": 22
}
Heat. A heating terminal, a radiator, a towel rail or a unit heater, has a power, and so a water flow at its design temperature difference (Part IV, 12.7). A terminal type's terminal.power is its power in W, from 1 to 500 000: what its elements give, unless one gives its own. A terminal's own terminal, beside its flow, gives:
| Member | Meaning |
|---|---|
power | its power in W, from 1 to 500 000, where it differs from its type's |
deltaT | its design temperature difference in K, from 1 to 80: the difference between its supply and its return water at which its flow is worked out |
kv | its valve's flow coefficient, kv, in m³/h at a pressure drop of 1 bar, from 0 to 1000 |
preset | its valve's presetting, as its maker writes it, 1 to 12 characters, a plain value |
A terminal's power is its own terminal.power, else its type's. A unit heater, a fan that blows air over a heating coil, is a terminal type of the kind unitHeater. A heating system's supply and return temperatures, from which an application takes a terminal's design difference where the terminal gives none, are the project's standards, an application value (open question 47).
The unit heater of a workshop, 3500 W at a design difference of 15 K; its type gives 3900 W:
{
"category": "terminal",
"height": 500,
"id": "unit-heater-a",
"levelId": "level-0",
"name": "Unit heater",
"offset": 2500,
"profile": [
[6000, 3000],
[6000, 2000]
],
"revision": 0,
"terminal": {
"deltaT": 15,
"power": 3500
},
"typeId": "type-unit-heater",
"width": 600
}
Where a terminal stands. A terminal's profile is its point in plan, and, where it gives a second point, the way it faces: from the first point toward the second. A terminal whose profile is one point faces plan +y. Its offset is the height of its base over its level (Part I, 4): a terminal stands from there up, whatever its mount, as the reference implementation places it (a ceiling outlet's base is where it hangs from the ceiling, a duct part's that names no duct half its height under the duct's axis). Its body is its declared geometry, its own or its type's, where it has one, else a box of its type's size (Part IV, 12.6). A component in a pipe or a duct stands where its run puts it instead (below).
Components in a pipe or a duct. A component is a valve, a pump, a strainer, a meter, an expansion vessel, a backflow preventer or an air vent in a pipe, or a damper, a silencer, a fan or a flow regulator in a duct: a terminal whose type's terminal.mount is pipe or duct, hosted on its run, the pipe or the duct it is in, at a distance along it. It follows its run. It has no connections of its own: the run stays one run through it, for its joins, its body and its quantities (Part IV, 12), and for what is derived from them. A component in a pipe is of one of these kinds, or a waterMeter:
| Kind | The component |
|---|---|
isolatingValve | an isolating valve, such as a ball valve |
checkValve | a check valve |
balancingValve | a balancing valve, which measures its flow and is preset |
controlValve | a control valve with its actuator |
safetyValve | a safety valve |
pump | a circulation pump |
strainer | a strainer |
energyMeter | a heat or energy meter |
expansionVessel | an expansion vessel |
backflowPreventer | a backflow preventer |
airVent | an air vent |
A component in a duct, by the steward's decision of 24 October 2026 (open question 51), is of one of these kinds, which Part VIII, 1.1 exports as the IFC4 classes the table gives:
| Kind | The component | IFC4: class, predefined type |
|---|---|---|
damper | a damper that controls or shuts off the air flow | IfcDamper, CONTROLDAMPER |
fireDamper | a fire damper | IfcDamper, FIREDAMPER |
smokeDamper | a smoke damper | IfcDamper, SMOKEDAMPER |
flowRegulator | a flow regulator, which holds the air flow through it at the flow it is set to | IfcDamper, BALANCINGDAMPER |
silencer | a silencer | IfcDuctSilencer, ROUND in a round duct and RECTANGULAR in a rectangular one |
ductFan | a fan in the duct | IfcFan, USERDEFINED, its ObjectType INLINE |
The kinds may have other mounts too: a pump on a floor is a pump mounted on the floor, and stands where its profile puts it, as any terminal does. A component in a pipe is its type's terminal.width across the pipe, terminal.depth along it and terminal.height up; a component in a duct is its size across (below) across the duct and up, and its type's terminal.depth along it (Part IV, 12.6). A component's type's code is the code its elements are tagged with, unless an element gives its own mark. Its system is not read: a component's system is its run's, with the run's number.
| Member | Meaning |
|---|---|
hostId | its run: its pipe, or its duct (rule 6) |
along | its distance from its run's first point, in mm, along the run's points in 3D: a vertical piece counts, as in the run's length (Part IV, 12.4, rule 2). At least 0; a component with no along is at 0 |
levelId, profile, offset | written from its run (below) |
width, height | in a pipe, its type's; in a duct, its size across, written from its duct (below) |
mark | optional: its own tag, such as V201 |
terminal | optional: a balancing valve's kv or preset |
Where a component stands. Let the run's points be P_0 … P_(m−1) (Part IV, 12.1, rule 1), and s = min(along, L), where L is the run's length. The component's point is the point at the distance s from P_0 along the run's points: on the piece where it falls, at the share s′ / l of the piece from its start, s′ the distance left and l the piece's length. Its way is the direction in plan of that piece; on a vertical piece, the way of the last piece before it that runs more than 1 mm in plan; and +y where none does. Its levelId is its run's. Its profile is two points: its point in plan, and the point 1000 mm from it along its way. Its offset is its point's height above that level less half its body's height, its type's terminal.height in a pipe and its size across up in a duct, so that its body is centred on the run's axis. The run and along are the intent; the three are the writer's copy of where they put it, as a hosted railing's line is (section 12.2, rule 4).
Its size across in a duct. A component in a duct is at least as large across as its duct, and stands 10 mm proud of it on each side, as a casing does. Let W and H be the duct's outer width and height, its size with its insulation (Part IV, 12.1, rule 3; a round duct is W across both ways). The component's size across is the larger of its type's terminal.width and W + 20 wide, and the larger of its type's terminal.height and H + 20 high, in mm. So one damper type fits a duct of any size, and a type that is larger, a silencer's casing or a fan's box, keeps its own size. Its length along the duct is its type's terminal.depth. The duct and the two types are the intent; the component's width and height are the writer's copy of its size across, as its place is.
When its run changes, a component keeps its along, and stands where the changed run puts it: a writer rewrites its levelId, profile and offset in the same command, and in a duct its width and height (rule 8). When the run gets shorter than its along, it stands at the run's end, and its along stays as it was: the run lengthened again puts it back. A command that moves a component's point and leaves its along slides it along its run. When its run is deleted, it is deleted with it, as every hosted element is (Part V, 5, rule 1).
A duct part that names no duct. A terminal whose type mounts on a duct and that gives no hostId is a terminal like any other: it stands where its profile and offset put it, its body is its type's box from its base up (Part IV, 12.6), and it does not follow a duct. The reference implementation placed its silencers, fans and fire dampers so before its work 676, and leaves them where they were put: such a model stays valid, and a writer hosts one by giving it a hostId and an along. Which systems it goes with in a view is section 13.1's.
A valve 2000 mm along the heating pipe above, on its first piece, which runs +x at 2400 mm above level 0; its type is 70 mm high:
{
"along": 2000,
"category": "terminal",
"height": 70,
"hostId": "pipe-heating",
"id": "valve-a",
"levelId": "level-0",
"mark": "V201",
"name": "Isolating valve",
"offset": 2365,
"profile": [
[3000, 1000],
[4000, 1000]
],
"revision": 0,
"typeId": "type-isolating-valve",
"width": 60
}
Its type:
{
"category": "terminal",
"color": "#b08d57",
"height": 70,
"id": "type-isolating-valve",
"material": "Brass",
"name": "Isolating valve",
"revision": 0,
"terminal": {
"code": "V101",
"depth": 80,
"height": 70,
"kind": "isolatingValve",
"mount": "pipe",
"width": 60
},
"width": 60
}
A damper 1500 mm along a rectangular supply air duct, duct-supply, 400 mm wide and 200 mm high without insulation, whose first piece runs +x from [1000, 5000] at 2700 mm above level 0. Its type is 145 mm across and 145 mm high, smaller than the duct, so its size across is the duct's and 10 mm each side, 420 mm by 220 mm, and its base is 110 mm under the duct's axis:
{
"along": 1500,
"category": "terminal",
"height": 220,
"hostId": "duct-supply",
"id": "damper-a",
"levelId": "level-0",
"mark": "D201",
"name": "Damper",
"offset": 2590,
"profile": [
[2500, 5000],
[3500, 5000]
],
"revision": 0,
"typeId": "type-damper",
"width": 420
}
Its type:
{
"category": "terminal",
"color": "#9aa0a6",
"height": 145,
"id": "type-damper",
"material": "Steel",
"name": "Damper",
"revision": 0,
"terminal": {
"code": "D101",
"depth": 200,
"height": 145,
"kind": "damper",
"mount": "duct",
"width": 145
},
"width": 145
}
- A run's
mep.system, a type'spipe.system,duct.systemandterminal.system, and thesystemof a terminal type's connection or outlet MUST be a system of the table above. The schemas state this rule. - An insulation code, a type's
insulationCodeor a run'scode, and each part of abtiare national values: a validator MUST NOT refuse one because a code list does not hold it (section 8, rule 4). The schemas mark them"x-eik-values": "national". - A run's
mep.insulationthat givesnoneSHOULD give nothing else. A duct's SHOULD NOT givebti. A run that gives its owncodeSHOULD give its ownthickness. btiis deprecated (Part I, 9.6): a writer SHOULD NOT write it, and SHOULD write the code and the thickness instead; a writer that does removes thebti. AbtiMUST giveclass,hanging,materialandthickness. A reader reads one as a code and a thickness: itsthicknessis the thickness, and its parts written together are the code:class,hanging,material, the thickness in mm as a whole number, and then-andsurfacewhere it has one. Where a type or a run gives abti, it stands in place of the code and the thickness beside it, as the reference implementation reads it. A validator SHOULD warn about eachbtia model holds, naming the code and the thickness to write instead.terminal.power,terminal.deltaT,terminal.kvandterminal.presetMUST be within the ranges of the tables above. The schemas state this rule.- A terminal whose type's
terminal.mountispipeMUST name a pipe of the model inhostId. A terminal whose type'sterminal.mountisductand that gives ahostIdMUST name a duct of the model there; one that gives none is a duct part that names no duct (above). - A component's
alongSHOULD be at most its run's length. A component whosealongis past its run's end stands at the end. - A component's
levelId,profileandoffsetSHOULD be where its run andalongput it: its level the run's, its point within 1 mm in plan, its way within 1°, itsoffsetwithin 1 mm. Thewidthandheightof a component in a duct SHOULD be its size across, each within 1 mm. A writer rewrites them in the same command whenever the run,alongor the component's type changes. A reader MUST follow the run andalong, and the size across, where they disagree. - A terminal type whose
terminal.mountispipeorductSHOULD NOT haveconnectionsoroutlets: a component is in its run, which stays one run through it, and no run's end joins it.
Reference: mepSystems and systemIds in src/core/elements/mepSystemList.ts (Stomra work 610); btiSchema and runInsulationSchema in src/core/elements/mepInsulationSchema.ts, and runInsulation in src/core/elements/mepInsulation.ts (615); terminalHeatTypeFields and terminalHeatFields in src/core/elements/mepHeatSchema.ts (616); onPipe, onDuct, alongRun, alongOf, componentBody (the size across, with DUCT_COLLAR), placedOnRun and followedRunComponents in src/core/elements/runComponents.ts, which was pipeComponents.ts (633, 676); componentMount and componentHost in src/core/elements/componentHost.ts (676); validateTerminal (rule 6), runOuter and terminalSystem in src/core/elements/mep.ts; and the types in src/core/elements/mepComponentPresets.ts and mepPresets.ts (633, 676). Plan 606 was built in five waves, on Stomra's main from 21 to 22 October 2026 (merge requests !240, !244, !249, !260 and !280); this text was written from its main at 43384047. Components in a duct are its work 676, live since 24 October 2026 (main f02ba07e); their text was written from its main at b7318113.
6.10 Provisions for voids
Part of 0.2. OpenEik 0.1 had it as the proposal provision: in a model of 0.1, read by 0.1's rules (Part I, 9.6, rule 3), a reader keeps a record of the category provision as a later version's (Part I, 10, rule 5). The section adds a category, provision, and the member provision of its elements, and no file; schemas/0.2/elements/provision.schema.json and schemas/0.2/types/provision.schema.json hold their schemas.
By the steward's decision of 30 October 2026 (open questions, section 4, D9; question 85, point 4), from the reference implementation's requests for openings (its work 670, step 6.1). A run that crosses an element another discipline owns, a duct through a wall, a pipe through a slab, a cable tray through a beam, needs a void there, which the element's owner makes. A provision records that need as a record of its own: its asker places it without changing the element, and the element's owner answers it. IFC calls it a provision for void.
A provision is an element of the category provision. Besides the members every element has (section 6), it carries provision:
| Member | Meaning | |
|---|---|---|
hostId | required | the element it goes through, its host (rule 3) |
axis | required | [x, y, z], a unit vector: the way it runs through its host |
up | required | [x, y, z], a unit vector square to axis: the way its height is measured |
depth | required | more than 0, at most 20 000 mm: its length along axis |
round | optional | true for a round void of diameter width; absent or false, a rectangle |
forIds | optional | 1 to 20 element ids: the runs it is for (rule 4) |
clearance | optional | 0 to 1000 mm: the space kept round its runs on each side, which its size includes |
note | optional | at most 400 characters: what it is for, in words for people (Supply air 400 × 200) |
answer | optional | its host's owner's answer (rule 5); absent, it waits for one |
answer is {state, by, at, discipline?, text?, cut?}:
| Member | Meaning | |
|---|---|---|
state | required | cut, the void is made; or declined, it is not |
by | required | 1 to 80 characters: who answered, as the project names them |
at | required | when, an RFC 3339 date and time in UTC (2026-10-30T09:15:00Z) |
discipline | optional | the discipline they answered for, one of the eight of Part XVI, 2, rule 4 |
text | required where state is declined | 1 to 1000 characters: why, in a sentence; optional where it is cut |
cut | required where state is cut | 1 to 20 entries, what the cut made: {"recess": "<id>"}, a recess of its host's recesses by its id, or {"element": "<id>"}, an element the cut made, such as an opening's own record; none where state is declined |
- Its place and its frame. Its
profileis one point, its centre in plan; its centre stands at its level's elevation plus itsoffset(Part I, 4).axisandupare unit vectors, their lengths within 10⁻⁶ of 1, and square to each other, their product within 10⁻⁶ of 0. With across,up×axis, they are its frame: across, up and axis as x, y and z, right-handed. A validator MUST report a provision whoseaxisorupis no unit vector, or whoseupis not square to itsaxis, as an error (provision-frame). - Its shape and its body. A rectangular provision is
widthalong across byheightalong up, centred on its centre; a round one is a circle of diameterwidth, and itsheightis not read. It runsdepthalongaxis, half each way from its centre. Its body is that prism: a box, or a cylinder from its centre lessaxis×depth/2 to its centre plusaxis×depth/2. - Its host.
hostIdnames a wall, a slab, a foundation, a ceiling, a roof, a beam or a column. A validator MUST report a host of another category as an error (provision-host). A host that is not in the model is a reference that does not resolve (Part I, 7, rule 3), which a validator SHOULD warn of: the provision waits for its owner to remove it. - Its asker.
forIdsnames the runs it is for, each a pipe, a duct or a cable carrier (Part XIII, 5). A validator MUST report an element of another category as an error (provision-run), and SHOULD warn of one that is not in the model. A provision is its asker's: in the owners' layout its owner is itsowner, else the owner of the run itsforIdsnames first, elsesetup(Part III, 4.4, rule 2). - Its answer is its host's owner's to give, and nothing else of the provision is theirs.
cutsays that the host's owner made the void with the host's own records, andanswer.cutnames what the cut made: a recess of the host, or an element.declinedsays that they did not, andtextsays why. A writer gives an answer once, and changes or removes it only for the host's owner. A validator MUST report an answercutwithoutcut, and an answerdeclinedwithouttextor withcut, as errors (the schema states this), and SHOULD warn of an entry ofcutthat names a recess its host does not have, or an element that is not in the model (provision-cut). - It cuts nothing. A provision is no void of its host, answered or not: the host's body is what the host's own records make it (Part IV). Its body (rule 2) is what a view, a print or a check shows of the void asked for. It counts in no quantity, cuts no other body, and a clash check does not take it for a part of the building. A view MAY leave out a provision whose answer is
cut, which what the cut made shows. - In IFC, a bridge writes a provision as Part VIII, 1.10 says: an IfcBuildingElementProxy of the predefined type PROVISIONFORVOID, its body rule 2's, with its size, its depth and its runs in IFC4's property set for a provision for a void.
- Commands. A command processor makes and changes a provision and its type as any element and type (Part V, 1, rule 5), holding each to this section's schemas. It refuses a command that gives a provision a host of a category rule 3 does not list (
provision-host), or a run of a category rule 4 does not list (provision-run). It keeps a provision whose host or run is not in the model, which the whole model's check warns of:provision.hostIdis nohostId, so adeleteof its host leaves the provision as it is (Part V, 5, rule 1), waiting for its owner to remove it (rule 3).
A duct's provision through an external wall, 450 mm wide and 250 mm high, its centre 1500 mm over level 0, asked by ventilation and not yet answered (compacted; on disk each member is a line):
{
"category": "provision", "height": 250, "id": "provision-a", "levelId": "level-0", "name": "Opening for supply air",
"offset": 1500, "profile": [[2000, 0]], "revision": 0, "typeId": "type-provision", "width": 450,
"provision": {"axis": [0, 1, 0], "clearance": 25, "depth": 220, "forIds": ["duct-supply-1"], "hostId": "wall-a",
"note": "Supply air 400 × 200", "up": [0, 0, 1]}
}
Its host's owner cuts it as a recess of the wall, wall-a's recesses entry provision-a-cut, and answers:
{"answer": {"at": "2026-10-30T09:15:00Z", "by": "A. Architect", "cut": [{"recess": "provision-a-cut"}], "discipline": "architecture", "state": "cut"}}
Reference: provisionSchema and provisionAnswerSchema in src/core/elements/provisionSchema.ts; provisionHosts, provisionRuns, validateProvision, provisionSolids, requestsFor, cutRecess, cutCommands and declineCommands in src/core/elements/provisions.ts; elementOwner in src/core/access/owners.ts (its asker); exportIfc in src/core/io/ifcExport.ts. In @openeik/tools: provisionChecks, provisionBody and provisionProperties in packages/openeik/src/provision.js.
7. References between elements
These element members name other elements. The list is the reference implementation's registry; a new member that names an element MUST be added to it.
| Path | Names |
|---|---|
hostId | the host: a wall for an opening, a slab or a foundation for a slab edge element, a slab, a foundation, a beam, a column or a slab edge element for a rebar element, a slab, a foundation or a wall for a mesh element (section 6.1, rule 6), a stair for its shaft, a stair, a slab or a shaft for a railing (section 12.2), a pipe or a duct for a component in it (section 6.9), a gutter's roof, the gutter a downpipe was made from (Part V, 2.3) |
top.attach.hostId, top.cutRoofId | the wall's attachment host and its cutting roof |
base.attach.hostId | the column's base host |
edgeAttachments[].hostId | a wall whose face trims an outline edge |
trussLayout.bearingWallIds[] | bearing walls of a truss layout |
mep.joins.start.terminalId, mep.joins.end.terminalId | the terminal a run's end joins |
joins[].to | the member or plate a member end is joined to |
framingTop.floorId | the floor a framing top follows |
bolts.through[] | the elements a bolt group passes through and drills (section 6.3); of 0.2 |
castWith | the element it is cast with in one pour (section 14.1); of 0.2 |
topRoofId, topCeilingId, roofCutId | legacy (section 6.4) |
hostId of an opening, top.attach.hostId, base.attach.hostId, edgeAttachments[].hostId, joins[].to, and the hosts of slab edges, gutters, rebar and mesh MUST resolve: the reference validator refuses the model otherwise. So MUST a railing's hostId and each id in its railing.edges, which names an edge of its host (section 12.2, rule 3), a component's hostId, which names a pipe or a duct (section 6.9, rule 6), and a top constraint's level, top.constraint.levelId of a wall, a shaft or a stair: its height cannot be worked out without it (Part IV, 5.1). The others SHOULD resolve. In 0.2, each id of a bolt group's bolts.through MUST resolve too, as the reference validator refuses a group whose through names no element (section 6.3, the note), and an element's castWith SHOULD.
Reference: ELEMENT_REFERENCES in src/core/model/copies.ts; validateElement, findAttachHost (wallTop.ts), findBaseHost (columnBase.ts), validateMemberJoins.
8. Profiles
A profile groups the members and payloads of one domain, so that a reader can say which domains it understands.
| Profile | Members (elements) | Payloads (types) |
|---|---|---|
| core | the members of section 6, hostId, along, voids, top, edgeAttachments, edgeIds, status, original, flipped, handFlipped, roomBounding, wallOutline, recesses, roof, joinEnds, declaredGeometry, generic | layers, section, windowFamily, openingFamily, outline, footing, wallAttach, declaredGeometry, generic |
| structure and fabrication | endRise, turn, roll, taper, base, connection, joins, holes, upright, axes, plate, bolts, weld, jointId, insertAt, edges | component, insert, edgeDetail, edgeProfile; pieces and joints |
| timber framing | framingParameters, framingTop, framingJoints, framingCorners, framingStart, framingOffset, framingStuds, framingTees, bottomPlate, frameHost, trussLayout | framing, the layers' framing and joists |
| reinforcement | reinforcement, bars, sheet | |
| systems | mep, terminal | pipe, duct, terminal |
| site | terrain, grading, propertyLine, road, parking, planting | road, parking, planting |
| interiors | room, kitchen | room, furniture |
| circulation | stair, railing | stair, railing, shaft |
| fire | fire, fireClass | fire, fireClass |
| documentation | views, detail items, scope boxes, dimension styles, detail families |
- A reader that does not implement a profile MUST keep that profile's members and records unchanged when it writes the model back.
- Profile members are flat members of the element, as the reference implementation stores them, and they stay flat (decided 11 October 2026). A model does not declare its profiles yet.
- No national code lists. OpenEik carries no national classification or code list (BSAB, CoClass, AMA, SS 21054 or any other) and defines no regional profiles. A field whose values come from such a list in practice is a plain string: a room type's area class (
room.ssClass), a view's area plan (display.areaPlan), the shape codes and grades of bars and cast-in bars, the designations and grades of mesh sheets, the precast reinforcement grades and meshes of the project, and the insulation codes of pipes and ducts and their parts (section 6.9). The schemas accept any non-empty string there and mark the field"x-eik-values": "national". A building-part catalogue (a type'sassembly) is an application value (section 9.2). - A reader MUST keep these values unchanged and MUST NOT need a code list to read them. A validator MUST NOT refuse a value because a code list does not contain it.
Why no regional profiles: a code list belongs to its publisher, who sets its licence and its editions. A standard that listed codes would have to license them, follow their editions and choose which countries' lists to carry, and an implementation would need them to conform. Leaving the values to their publishers keeps OpenEik usable with any system, in any country. Classification references (section 11) let a record name a code of any system without the standard licensing or listing it.
9. Application records and values
9.1 Application records
Title blocks, images, reports, renders, deviations, area adjustments and linked references are records of the application that wrote the model. OpenEik carries them but does not define them.
In 0.1, drawing production stays with the application: sheets, title blocks and images remain application records and do not join the documentation profile (decided 11 October 2026). In 0.2, sheets and issued drawings join the standard (the steward's decision of 15 October 2026): a sheet is a record of Part XIV, 2, and a sheet of 0.1 that is not one stays an application record (Part XIV, 2.1, rule 1; Part I, 9.8, rule 5). Title blocks and images stay application records.
- Each is a JSON object with an
id;application-record.schema.jsonchecks only that. - A reader MUST keep application records unchanged when it writes the model back, and MUST NOT require them.
- A writer MAY omit them.
9.2 Application values
Some members of defined records hold application values: a type's assembly (a building-part catalogue), catalogSource and handbook, the project's standards, the font choices of views and dimension styles, a symbol's name and a port's, and the rows of a tag template (section 13). The schemas mark them "x-eik-application": true and accept any value of the right JSON type. A reader MUST keep them unchanged. They are the application's, not the standard's: OpenEik does not define a catalogue, a handbook, a drawing standard or a font (decided 11 October 2026). An application's own data beside them goes in extension members and in its own folder (Part I, 11).
10. Derived data is not a record
Bodies, meshes, joins found from geometry, room boundaries and areas, quantities, framing members derived from a rule, stair runs, fittings and the elements of placed copies are derived (Part IV). They MUST NOT be stored as records. Two kinds of record come from derived data because a person or a command made them so:
- materialised members: framing members or trusses written as elements by a command (
framing.materialise,trusses.materialise) carryframeHostand are ordinary elements from then on; - originals and copies: a placed group is stored as its original's elements plus a
copyrecord; the copy's elements are derived and named<copy id>/<element id>, and are never stored.
A view is a record (its settings and its 2D items); the drawing it shows is derived.
Reference: storedOf and workedOut in src/core/model/copies.ts; migrateManifest drops stored copy elements on load.
11. Classification references
Part of 0.2. OpenEik 0.1 had it as the proposal classifications, and this section was informative: in a model of 0.1, read by 0.1's rules (Part I, 9.6, rule 3), classifications is a member a schema of 0.1 does not know, which a reader keeps (Part I, 10). The section adds this one member and no file.
By the steward's decisions of 11 October 2026 (open questions, 4) and 27 October 2026 (open questions, 86, "C ja"): a record names codes of classification systems that OpenEik does not list, so that any system can be used without the standard licensing or listing it.
{
"classifications": [
{
"code": "<code>",
"edition": "<edition, optional>",
"system": "<name or URI of the system>",
"uri": "<the code's URI, optional>"
}
]
}
- Which records. Any record MAY carry
classifications, a list of 1 to 100 references, at its top: the project, in itsproject; a level; and each record of the record lists (Part III, 9), whatever its kind: a grid, a material, a type, an element, an original, a copy, a view and the rest. The order, which is no record, and a view's detail items, which are parts of their view, carry none. - A reference is
{system, code, edition?, uri?}.systemnames the classification system, by its name or a URI, 1 to 200 characters;codeis a code of that system, 1 to 100 characters;editionnames the system's edition, 1 to 100 characters, where it matters which; andurinames the code itself, by the URI its publisher gives it, such as its URI in buildingSMART's Data Dictionary (bSDD): an absolute URI (RFC 3986), at most 2000 characters. A writer SHOULD giveuriwhere the publisher gives one, so that a reference names its code the way buildingSMART's IFCX names a node's class, by a bSDD URI. A member of a reference that this section does not define is one a reader keeps, as in any record (Part I, 10). - Several references. A record MAY carry several references, of one system or of several. It MUST NOT carry one reference twice. The order of the list has no meaning.
- No list of systems or codes. OpenEik does not list systems or codes, and a validator does not check that a code is one of its system's: the system's publisher defines its codes and their licence, and the writer of the record says which system it uses. A validator MUST NOT refuse a reference because it does not know its system or its code.
- Beside, never in place of. The plain strings and application values of sections 8 and 9.2 stay as they are: a classification reference is added beside them, never in their place, and a reader reads neither from the other.
- A bridge that writes IFC writes each reference of a record it prints an object for as an IfcClassificationReference of its system (Part VIII, 1.8), its
Identificationthe code and itsLocationtheuri, and says in its fidelity report which references it does not print.
The class 21.21 of NL-SfB, as buildingSMART's IFCX examples classify a wall: {"system": "NL-SfB", "edition": "2005", "code": "21.21", "uri": "https://identifier.buildingsmart.org/uri/nlsfb/nlsfb2005/2.2/class/21.21"}. A wall may carry it beside a code of another system, {"system": "Uniclass", "edition": "2015", "code": "EF_25_10"}, which gives no URI here.
12. A supplier's parts
The records of this section serve the supplier proposal flow, which the steward approved on 11 October 2026: a supplier's declared geometry (12.1) and railings for product systems (12.2). Their principles were decided on 11 October 2026 and proposed for 0.2; on 14 October 2026 they were adopted into 0.1 (open questions 17 and 18). types/type.schema.json and elements/element.schema.json define declaredGeometry and the members of railing, and the category schemas add the rules of each category.
In the supplier proposal flow, the supplier of a building part (railings first, then any part) is invited to a project. It reads a named version, finds its parts by category, and checks them with its own tool. It proposes changed records as typed commands (Part V), with a quote. The client merges one proposal. The quote lives with the proposal on the host: it is not part of the model.
12.1 Declared geometry: a part at a declared level of detail
The principle. A supplier's records can carry geometry at any level of detail, the supplier's choice. It ranges from the interface only up to the full manufacturing model:
- The interface is what other trades and checks meet: the exact outer envelope, the fixing and connection points, clearances, positions such as posts and fixings, the loads the part puts on the structure, and the declared tolerances. It is enough for exact geometric checks and layout control, and it is a valid minimum, not the rule.
- The implementation is the supplier's own to keep back or to share: internal profiles, joints, machining and cutting data, article numbers. A supplier that shares none of it publishes the interface, not the implementation; one that shares all of it publishes its manufacturing model.
- Costs, prices and quotes are never part of a record. In the supplier flow the quote lives with the proposal on the host.
A record says how far it goes: it declares its level and what its geometry is authoritative for. As in a code base, a library may ship only its interface, its declarations, and keep its implementation: a compiler checks every use against the interface exactly and assumes nothing about the code behind it.
Where it lives. A type or an element MAY carry declaredGeometry:
- On a type, for geometry that is the same for every element of the type: a window, a door, a component, a railing's section. Its coordinates are in the type's frame:
- a category placed at a point (
component,furniture,terminal,column,generic): the element's insertion point at its base, x along its orientation, z up; a component withaxes, the frame they give (section 6.3); - a hosted opening (
door,window): x along the host wall from the opening's near edge, y across the wall from its centreline towards the wall's exterior side (Part I, 5.1), z up from the opening's bottom; - a category placed along a line (
railing,beam,slabEdge,gutter): a section square to the line (x across it, z up from the line's base), swept along the whole line.
- a category placed at a point (
- On an element, for geometry that depends on where the element is: the posts and fixings of a railing along given edges, a stair kit in a given shaft. Its plan coordinates are those of the element's
profile(the project's, in mm); its heights are measured from the element's base,elev(levelId) + offset(Part I, 3.3 and 4).
For each aspect, an element's declaration wins over its type's; the aspects an element does not declare come from its type's.
A type of a category that this list does not name (a stair's, a slab's, a wall's …) has no frame in 0.1. Its declaration is kept and checked as any declaration is, but placed nowhere: a compiler derives nothing from it (Part IV, 11.1), and a check cannot use it. Such a part declares its geometry on its element, in the world frame (rule 7). From 0.2 a stair's type and a wall's type have a frame (section 12.1.1).
A window type declaring its interface, in its own frame (compacted; on disk each member is a line):
{
"declaredGeometry": {
"authoritativeFor": ["envelope", "fixings", "clearances"],
"clearances": [
{"body": {"bottom": 0, "kind": "prism", "profile": [[0, -45], [1200, -45], [1200, -650], [0, -650]], "top": 1200}, "id": "sash-swing", "purpose": "operation"}
],
"envelope": [
{"bottom": 0, "kind": "prism", "profile": [[0, -45], [1200, -45], [1200, 45], [0, 45]], "top": 1200}
],
"fixings": [
{"at": [0, 0, 200], "bearsOn": "reveal", "direction": [-1, 0, 0], "id": "fx-1"},
{"at": [0, 0, 1000], "bearsOn": "reveal", "direction": [-1, 0, 0], "id": "fx-2"},
{"at": [1200, 0, 200], "bearsOn": "reveal", "direction": [1, 0, 0], "id": "fx-3"},
{"at": [1200, 0, 1000], "bearsOn": "reveal", "direction": [1, 0, 0], "id": "fx-4"}
],
"level": "interface",
"tolerances": {"default": 2, "fixings": 1}
}
}
The window's profiles, its sash and its glazing are not declared: a check knows the space the window takes, where it is fixed and what must stay free in front of it, and nothing about what is inside.
The levels. level is one of three, in order:
| Level | The geometry is | It MAY be authoritative for |
|---|---|---|
interface | the part as other trades meet it: the space it takes, where it is fixed, what must stay free, and the positions and loads that matter to others | envelope, fixings, clearances, positions, loads |
assembly | the interface, and each separate part as installed (posts, rails, panels, brackets, a sash), with its outer body and its place | the above, and parts |
fabrication | the full manufacturing model | the above, and fabrication |
What it is authoritative for. authoritativeFor lists the aspects the geometry is exact for, from this closed vocabulary:
| Term | The declaration states, exactly within its tolerance |
|---|---|
envelope | the outer envelope: the whole space the part takes as installed, as bodies |
fixings | the fixing and connection points: where the part is fixed to another record or connects with it, in which direction, and which face it bears on |
clearances | the zones that must stay free: to install, operate (a sash's or a leaf's swing), maintain or replace the part |
positions | the set-out points or lines of the part's distinguishable members (posts, brackets, mullions, hinges), without their shapes |
loads | the loads the part puts on the structure at each fixing, per named load case, as characteristic forces in kN and moments in kN·m in the model's axes |
parts | the separate parts as installed, each with an id, a name and its outer body |
fabrication | fabrication data: internal profiles, joints, machining, cutting and assembly data. OpenEik does not define its form: it is the supplier's application value (section 9.2), or the supplier's kept files (Part III, 7) named by path and hash |
Rules:
levelandauthoritativeForare required.authoritativeForMUST containenvelope, MUST name each term once, and MUST name only terms its level allows.envelopewith any offixings,clearances,positionsandloadsis a complete declaration at theinterfacelevel.- A declaration MUST carry data for every term it lists, and MUST NOT carry data for a term it does not list.
tolerancesgives, in mm, how far the built part may lie from what is declared: adefault, and a value per term where it differs; it has no other members. Every geometric term listed (envelope,fixings,clearances,positions,parts) MUST have a tolerance, its own or the default.- Bodies are of the body kinds of Part IV, 8, written with these
kindnames:prism{profile, bottom, top};polyhedron{vertices, faces}(convex);mesh{vertices, faces}(closed);cylinder{centre, radius, bottom, top};rod{from, to, diameter}; and, on a type placed along a line,swept{section: [[x, z], …]}, with x across the line towards the walking side, swept piece by piece along each segment. In thelineframe a body is mapped point by point, so it bends only at its vertices: a line-frame body SHOULD stay within one segment of the line. The other records: a clearance is{id, purpose, body}; a position is{id, member?, at, to?}, withtofor a position along a line; a load is{fixing, case, force, moment?}, in kN and kNm, acting at the declared fixing whoseiditsfixingnames; a part is{id, name, bodies}. A writer that mirrors a declaration (rule 6) MUST reflect a load's force, and reflect its moment and then change its sign, since a moment is an axial vector: with the reflection R, F' = R·F and M' = −R·M (mirroring x → −x turns M (4, 5, 6) into (4, −5, −6)). - An element's declaration SHOULD name its
basis: the id and the hash (Part III, 6: SHA-256 of the record's canonical JSON, the function the version tree uses) of each record it was made against, such as the host and the edges it follows. A reader reports a basis whose hash has changed, keeps the declaration, and treats it as unconfirmed. - A writer that moves, turns, mirrors or copies an element (the transforms of Part V, 2.3) MUST move, turn, mirror or copy its declared geometry with it.
- The frame of an element's declaration.
frameisworld(absent: the project's plan coordinates, as above) or, for a category placed along a line,line: a point is[s, w, z], withsthe distance in plan along the element's line from its first point,wthe distance across it towards the walking side, andzthe height over the element's base. A declaration in thelineframe follows its host's line the wayrailing.posts.atdoes. - A fixing gives its
id, its pointatand itsdirection(a unit vector), and SHOULD say what itbearsOn(reveal,edgeFace,slabTopand so on). It MAY give itskind(bolt,anchor,bracket,screw…) and itssizein mm. - Who declared it. A declaration MAY name its
source: who made it and with what, as{"by": …, "tool": …, "version": …}. It says nothing about responsibility; a host's signed merge records that.
The schemas state rules 1 to 3 and the shapes of rules 4, 5 and 7 to 9: fabrication is marked as the supplier's application value, a swept body is allowed only in a type of a category placed along a line, and the line frame only on an element of such a category. A validator checks the rest in code, such as that a load acts at one of the declaration's fixings.
Reference: declaredGeometrySchema in src/core/model/declaredGeometry.ts (rules 1 to 3, the shapes of rule 4, rules 5 and 7 to 9); mappedDeclaration there, called by the transforms (rule 6); unconfirmedBasis (rule 5).
How readers, checks and compilers treat it.
- Exact for what it declares, silent on the rest. A reader, a check or a compiler MUST use declared geometry only for the aspects its
authoritativeForlists, and MUST NOT infer from it anything about the others: an envelope says nothing about the parts inside it. - Readers keep it unchanged (Part I, 10). A viewer MAY draw the declared envelope, or the declared parts, in place of the body a compiler derives from the type's payload, and SHOULD say that it shows a supplier's declared geometry, at which level.
- Checks use what is declared. A clash check uses the declared envelope, grown by its tolerance, in place of the derived body, and treats each clearance, grown by its tolerance, as space no other body may enter. A layout check uses the declared positions and fixings: a fixing MUST lie on the face it names, within its tolerance. For an aspect that is not declared, a check uses the derived body and says so in its result. A check that needs an aspect that is not declared (the gaps between balusters need
parts) MUST report that the declaration cannot decide it: it neither passes nor fails it. - Compilers derive nothing beyond what a record declares itself authoritative for (Part IV, 11.1).
- A changed basis. When a record named in
basishas changed since (its hash differs), the declaration was made for another version of that record. Readers keep it and checks still use it, but they report it as unconfirmed until the supplier confirms or replaces it. It is never discarded.
Declared, not derived. Section 10 and Part IV, 1, keep derived data out of records. Declared geometry is not derived data:
| Derived data (Part IV, 1) | Declared geometry | |
|---|---|---|
| Made by | a compiler, from the model's records, by the rules of this specification or a reference rule | the supplier, from its own product and its own rules, which are not in the model |
| Made again from the records? | yes: deleting it loses nothing | no: deleting it loses the supplier's statement |
| Where it lives | never in a record; at most in .eik/derived/, keyed by the hashes of its sources (Part IV, 1.1) | in the record, a type or an element, written by a command and merged by a person like any other change |
| When its sources change | discarded and derived again | kept, and reported as unconfirmed (rule 5 above) until the supplier confirms or replaces it |
| Authority | the rule that made it | exact for what it declares, within its tolerances; silent on the rest |
A declaration is source, as a door type's sizes are (section 5.3): what a supplier states about its product. Nor is it a materialised member (section 10): those are written from the model's own derived data, and the model's rules could make them again; nothing in the model can make a declaration again. What a compiler works out from a declaration (its bounds, a section through its envelope) is derived as before, and is not stored.
12.1.1 Nominal sizes, and a stair kit's and a prefabricated wall's frame
Part of 0.2. OpenEik 0.1 had it as the proposal declared: in a model of 0.1, read by 0.1's rules (Part I, 9.6, rule 3), a declaration on a stair's or a wall's type is placed nowhere, as section 12.1 says. The section adds no file and no member.
By the steward's decision of 21 October 2026 (open questions, 17), on the two questions deferred on 15 October 2026. Suppliers ship a stair kit and a prefabricated wall whole, and declare them on their type, as they declare a window.
- Nominal sizes. The sizes a type sets (section 5.3) need not agree with its declared envelope. They stay its nominal sizes, which schedules and tags show, and the declared envelope is the part's geometry where a body stands for the space it takes (Part IV, 11.1, rule 2). A validator MAY warn where a size differs from the envelope's extent in the type's frame by more than the declaration's tolerance for
envelope, its own or itsdefault(declared-size):widthfrom the extent along the frame's x,heightfrom the extent along its z. - A stair's type, a stair kit's: its declaration's frame has its origin at the stair's start, its profile's first point, at its base,
elev(levelId) + offset; x runs up its first run, towards the profile's second point in plan; y to its left, looking up the stair; z up. It is the stair's frame of Part IV, 7.3. - A wall's type, a prefabricated wall's: the origin at the baseline's first point, at the wall's base,
elev(levelId) + offset; x along the baseline; y to its left, the wall's exterior (Part I, 5.1); z up. The wall's top, attached or of its own outline (Part IV, 5.3), moves nothing in the frame. - Other categories. A type of a category that neither section 12.1 nor rules 2 and 3 give a frame keeps none: its parts declare their geometry on their element, in the
worldframe (section 12.1, rule 7). - A compiler places a stair's and a wall's type's declaration in these frames, as section 12.1 places the others' (Part IV, 11.1): its envelope stands where the element's body stands for the space it takes.
A prefabricated wall element 2400 mm long, 3000 mm high and 210 mm thick declares on its type the envelope {"bottom": 0, "kind": "prism", "profile": [[0, -105], [2400, -105], [2400, 105], [0, 105]], "top": 3000}, centred on the baseline as a wall's body is (Part IV, 4.1), its fixings at its foot, [600, 0, 0] and [1800, 0, 0], and its tolerances {"default": 3}. Each wall of the type places it at its own baseline's first point, along its baseline, its exterior face at y = 105.
12.2 Railings for product systems
A railing supplier's tool details railings on the edges of slabs and makes them. Without the members of this section, a railing's records are too thin for a product system, and two implementations place the posts of one railing differently. In a study of 11 October 2026, a railing on three edges of a balcony slab, written with the reference implementation's commands, got eight posts from the reference implementation and eight from a railing supplier's tool: at the corners in one, 200 mm from them in the other. This section adds what a product system needs.
The members. An element's railing is {side?, edges?, inset?} and the members added below. A type's railing has thirteen members, kind (balusters, glass, panel or handrail), height, postSpacing, post, railWidth, railDepth, baluster, gap, clearance, panel, handrail, handrailDiameter and material, each required by the kinds that use it (the table below), and the members added below. A railing's line, posts and infill are reference behaviour (Part IV, 7.2), except the line of a railing on an outline and its given posts (Part IV, 11.2).
Host and edge rules (section 6.1, rule 11, and section 7). The reference implementation checks them.
- A railing's type MUST have a
railingpayload. - A railing stands on a stair, on the outline of a slab or a shaft, on a wall's top, along a slab edge element, or on a line of its own:
- on a stair:
hostIdnames the stair, andrailing.side(leftorright, looking up the stair) MUST be given; - on an outline:
hostIdnames a slab or a shaft, andrailing.edgesMUST be given: ids of the host's edges (itsedgeIds, or<host id>:edge:<n>where it has none; Part I, 6.6) that follow one another round the outline as one run. Naming every edge makes a closed run; - on a wall's top or along a slab edge element:
hostIdnames the wall or the element, andrailing.side,railing.edgesandrailing.insetsMUST NOT be given (below); - with no host: its
profile, two points or more, is its line, and its base iselev(levelId) + offset.
- on a stair:
- A railing's
hostId(a stair, a slab, a shaft, a wall or a slab edge element) and each id inrailing.edges(an edge of its host) join the references that MUST resolve (section 7). - A railing on an outline stands on its host's top along its line (Part IV, 11.2); a railing on a stair is measured from the stair's nosing line (reference behaviour). A hosted railing's
profile,levelIdandoffsetare written from its host: a writer rewrites them in the same command whenever the host changes. The profile is the railing's line in plan, the level is the host's (for a shaft with a top constraint, that constraint's level), and the offset is 0. The host and the edges are the intent; the profile is the writer's copy of the line. A reader MAY use it for a railing on an outline, MUST follow the host where the two disagree, and gets no heights from it for a railing on a stair. From 0.2 the copy of a railing on an outline is deprecated, and such a railing may leave it out (section 12.2.1). railing.sidehas a meaning only on a stair, andrailing.edgesandrailing.insetsonly on an outline.
Reference: validateElement in src/core/model/model.ts ("A railing needs a railing type.", "A railing on a stair names its side: left or right.", "A railing on an outline names the edges it runs along."); railingLine and chain in src/core/elements/railings.ts; followedRailing in src/core/elements/hostedFollow.ts.
The members added for product systems, all optional, so that a railing written without them stays valid and keeps its shape. On the type's railing:
| Member | Meaning |
|---|---|
mount | top: the posts stand on the host's top (the default, and the behaviour of a railing without this member). side: the posts are fixed to the host's edge face and reach belowBase below its top |
postWidth, postDepth | a rectangular post: its size along the line and across it, in mm. Without them a post is post by post |
postEndDistance | how far the first and the last post stand from the ends of the line, in mm, where the element gives no posts.at. Absent: 0 |
belowBase | how far the posts and the infill reach below the base, in mm, for side mounting. Absent: 0 |
topRail | the top rail's shape: rectangular (railWidth by railDepth, the default), round (diameter railWidth), halfRound or flat |
panelPattern | a panel's pattern, for the kind panel: solid, perforated or corrugated |
corner | how rails and infill meet at a corner of the line: mitre or square. Absent: the rails run past each other |
On the element's railing:
| Member | Meaning |
|---|---|
insets | per edge, by edge id: that edge's inset where it differs from inset (outline hosts only) |
posts.at | the posts' positions: distances in mm along the railing's line from its start, measured in plan, in increasing order. They do not move when an inset changes |
posts.omit | a list: ["start"], ["end"] or both: the ends that have no post of this railing, because a neighbouring railing's post or a wall carries them. With posts.at, the list of posts is complete, and omit only says which ends a neighbour carries |
Not every member for every kind. A type's railing MUST give the members its kind requires, and need not give the others. (Until 14 October 2026 every railing type gave all thirteen, even those its kind does not use: panel for balusters, handrailDiameter without a handrail.)
| Member | Required for |
|---|---|
kind, height, postSpacing, railWidth, railDepth, material | every kind |
post | every kind, unless postWidth and postDepth are both given |
baluster, gap | balusters |
clearance | balusters, glass, panel |
panel | glass, panel |
handrailDiameter | a type whose handrail is more than 0 |
handrail | none: absent means 0, no handrail on the walking side |
A member a kind does not use MAY be present, and readers ignore it for that kind. gap is the widest clear opening between balusters, not their spacing centre to centre. The type schemas state this table; the element schema states that posts.omit names each end once.
Posts are normative when given. If railing.posts.at is present, a post stands at each distance it lists along the railing's line, and nowhere else: every reader, compiler and check places them there (Part IV, 11.2). Otherwise the post layout is reference behaviour, within the type's postSpacing and postEndDistance. A supplier's tool writes its post layout with an update of posts.at, as framing members are materialised (section 10): the product's rules stay in the supplier's tool, and their result is in the record, so every tool shows the same posts. When the line changes later (the host is reshaped), posts.at stays as written, and a check reports a post that is off the line or a span longer than postSpacing.
A side-mounted railing with balusters on three edges of a balcony slab, the railing of its type and of its element (compacted; a synthetic example):
{
"baluster": 20, "belowBase": 300, "clearance": 0, "corner": "mitre", "gap": 98,
"height": 1150, "kind": "balusters", "material": "Aluminium", "mount": "side",
"postDepth": 50, "postEndDistance": 200, "postSpacing": 1200, "postWidth": 30,
"railDepth": 35, "railWidth": 50, "topRail": "halfRound"
}
{
"edges": ["slab-balcony-a:edge:3", "slab-balcony-a:edge:0", "slab-balcony-a:edge:1"],
"inset": -25,
"insets": {"slab-balcony-a:edge:1": -40},
"posts": {"at": [200, 1308, 1525, 2633, 3525, 4642, 5675, 5900]}
}
The type gives no panel, handrail or handrailDiameter: its kind does not use them. The supplier's product identity can travel in the type's catalogSource (section 9.2); its article numbers stay in its own folder, or in a declaration authoritative for fabrication if it chooses to share them (section 12.1).
Details decided with the reference implementation (11 October 2026):
- A corner where two edges have different insets is where the two moved edge lines cross; if they are parallel, or cross farther than four times the larger inset from the corner, it is halfway between their ends. When every edge of the run has the same inset, a corner moves along its bisector instead (Part IV, 11.2, rule 3): the two rules agree except at turns sharper than about 151°, where the moved lines cross farther than four times the inset from the corner, and the bisector rule stops there, at four times the inset.
- A post rises to the underside of the top rail, and the top rail carries the railing to its
height(Part IV, 11.2). - A position in
posts.atbeyond the line's end is not refused: a check reports it, as it reports a span longer thanpostSpacing. panelPatternis a property of the panel; a compiler need not draw it.
Reference: railingTypeSchema and railingElementSchema in src/core/elements/railings.ts (the members, and what each kind requires).
On a wall's top and along a slab edge element. By the steward's decisions of 21 and 24 October 2026 (open questions, 18), in 0.1 since 24 October 2026, as the reference implementation builds them since Stomra 643. Part IV, 11.2 derives the line (its rules 8 to 11).
- A railing on a wall's top names the wall in
hostId; a railing along a slab edge element names the element. Both join the references that MUST resolve (section 7). - On these hosts,
railing.side,railing.edgesandrailing.insetsMUST NOT be given (rule 2 above).railing.insetandrailing.posts(at,omit) mean what they mean on an outline. railing.inset, from −1000 to 1000 mm, is the distance of the railing's line from its host's outer face towards its inside: from a wall's exterior face (Part I, 5.1), from a slab edge element's outer face. Without it, the line runs along the middle of the host's top.- Its
levelIdis the wall's level, or the level of the slab whose edge the element follows; itsoffsetis 0. Its line is derived: itsprofileis not read. 0.1's schemas ask for a profile of one point or more, so a writer writes one point there, which means nothing; from 0.2 it may leave the profile out, as the derived line of a railing on an outline lets it (open questions, 18). - Its walking side is a wall's interior (the right of its directed baseline), or the side of the slab. It has no member of its own: a wall turned round turns the railing with it, as its layers turn (Part I, 5.1), and a given
insetandposts.atare read from the turned wall's faces and ends. - When its host is deleted, the railing goes with it, as a hosted element does (Part V, 5, rule 1).
12.2.1 A hosted railing's profile
Part of 0.2. OpenEik 0.1 had it as the proposal railings: in a model of 0.1, read by 0.1's rules (Part I, 9.6, rule 3), every railing carries a profile, as 0.1's element schema asks, and rule 4 of section 12.2 stands. The section adds no file and no member.
By the steward's decisions of 21 and 24 October 2026 (open questions, 18). The line of a railing on the outline of a slab or a shaft, on a wall's top or along a slab edge element is derived (Part IV, 11.2), a class-A rule; from 0.2 nothing of it is copied into the record.
- On an outline. The
profileof a railing on the outline of a slab or a shaft is no longer its writer's copy: the copy is deprecated (Part I, 9.6). A reader derives the line from the host and its edges, and ignores a profile it finds; a writer does not rewrite it when the host changes, and SHOULD NOT write it. Such a railing MAY leave outprofile. ItslevelIdandoffsetstay as rule 4 of section 12.2 writes them: the host's level, for a shaft with a top constraint that constraint's level, and 0. - On a wall's top or along a slab edge element. A railing MAY leave out
profile, which means nothing there (section 12.2, "On a wall's top and along a slab edge element", rule 4): the one point 0.1's schema asks for is deprecated, and a writer SHOULD NOT write it. - On a stair. A railing on a stair keeps its copy: its
profile,levelIdandoffsetare written from its host as rule 4 of section 12.2 says, and a reader gets no heights from them, until a stair's flights have a class-A rule its line can follow. A railing with no host has its profile as its line, as before. - What a validator checks. A railing that names a host and no
railing.side, which so stands on no stair (rule 2 of section 12.2), need not carry aprofile. A validator SHOULD warn about theprofileof a railing on an outline, a wall's top or a slab edge element (railing-profile), and a writer that reads one removes it.
A railing on three edges of a balcony slab is {"category": "railing", "hostId": "slab-balcony-a", "levelId": "level-1", "offset": 0, "railing": {"edges": ["slab-balcony-a:edge:3", "slab-balcony-a:edge:0", "slab-balcony-a:edge:1"], "inset": -25}, …}, with no profile; its line is the run of those edges, moved by its inset.
13. Views and detail items of building services
Views and their detail items, the 2D items of a view, are records of the documentation profile (sections 1 and 8; Part III, 10), held to their schemas. This section says what the members of heating, ventilation and plumbing drawings mean, by the steward's decisions of 23 and 24 October 2026 (open questions 48 to 50): a view's filter by system, frames and the white ground of texts and tags, the tags of pipes, ducts and terminals, the room tag, and symbols with lines joined to their ports. What a view shows is derived, and drawing it is the application's (section 10).
13.1 A view's filter by system
A view's visibility.systems shows some systems and hides the others: {mode, ids}.
| Member | Meaning | |
|---|---|---|
mode | required | show: the view shows the systems named, and hides the others; hide: it hides the systems named, and shows the others |
ids | required | 1 to 40 systems: a system of section 6.9 (coldWater), or a system and its number after a colon (heating:20) |
A system without a number names that system under every number; with one, under that number only. heating:1 names the heating runs whose mep.number is 1 or absent.
- A pipe or a duct is hidden when its system and number are.
- A component in a pipe or a duct (section 6.9) is hidden when its run is.
- A duct part that names no duct (section 6.9) goes with the duct it stands on, where it stands on one, and is otherwise another terminal; the reference takes the nearest duct within 300 mm in plan.
- Another terminal is hidden when every system it serves is hidden: the systems and numbers of the runs whose ends join it (
mep.joins), else the systems of its type and its connections, under any number. - Their tags go with them, and so do their bodies in a section or a 3D view.
A dependent view takes its parent's filter with the rest of its visibility. How a drawing shows what the filter hides, left out or in halftone, is the application's.
13.2 Frames and the white ground
A detail item's textFrame draws a frame round its text: {shape, margin?, weight?}.
| Member | Meaning | |
|---|---|---|
shape | required | rectangle, rounded (a rectangle with rounded corners), or none: no frame, where the view would give one |
margin | optional | the gap between the text and the frame, in paper mm, from 0 to 10; absent, 1 |
weight | optional | the frame's line width, in paper mm, from 0.05 to 2; absent, 0.25 |
A view's display.textFrame is the frame of its texts, leaders and tags that give none of their own; display.mepTagFrame the frame of the plan's automatic tags of pipes, ducts and terminals (13.3). An item's own frame wins over its view's, and none leaves out the view's. The frame is measured from the text's extent, so it follows the text, its size and the view's scale: its sides lie margin outside the text's box, and a rounded frame's corners have a radius of half its height, at most 1.5 paper mm. A leader leaves from the frame's edge.
A detail item's textBackground, opaque or transparent, says whether its text stands on a white ground that hides what lies under it; a view's display.textBackground is that of its texts, leaders and tags that give none of their own, and without either the ground is transparent. A dimension style has its own (textBackground), as in 0.1.
A frame and a ground mean something on a text, a leader and a tag; on another item they are kept, and draw nothing.
13.3 Tags of pipes, ducts and terminals
The plan's automatic tags. A plan tags its pipes, ducts and terminals by itself: a run's designation (its system, number, material code and size) and a terminal's code, as the application writes them. A view's display.mepTags says how many: each, the default, tags every run and terminal; perRun tags one run of each chain of runs joined end to end with one designation and size, the longest in plan, and every terminal; none tags none. A view's mepTagEdits keeps, by an element's id, what was done to that element's automatic tag in the view: offset, where it stands, in the view's mm from where the plan puts it; hidden, true where it is not drawn; and elbow, true where its leader runs at right angles, along to the tag's height and then across to its edge. The tag stays the element's: it follows the element, and can be moved one by one.
Lined-up tags are drawing behaviour: an application's command (the reference's tags.lineUp) stands the tags of chosen elements in a column or a row outside the building, and writes what it did as each tag's offset and elbow in mepTagEdits. It adds no member.
A terminal type's terminal.tagSize, false, leaves its size out of its elements' tags; it is 0.2's (section 14.6).
A tag placed by hand is a detail item of the kind tag (section 1). Its tag.field mep reads the element's automatic tag: a run's designation, a terminal's code.
Tag templates. A view's display.mepTagTemplates says what its tags of pipes, ducts and terminals read, {pipe?, duct?, terminal?}, each {rows}: one to three rows, each of 1 to 120 characters. A template is the view's data: it travels with the view, so that another application reading it knows what the view's tags are to read. Its rows are written in the application's own language of fields, an application value (section 9.2; open question 49). A tag's text, the template filled in, is derived, and never stored.
13.4 The room tag
A tag of the field room tags a room: its tag.elementId names the room. It stands at the room's label point, follows the room, and may have a frame (13.2). The tag is model data, a detail item of its view as any tag is; what it reads is derived: the room's number and name; the codes of the fixtures in it, counted; its air terminals by code and size; and its supply and extract air flows summed, in l/s. A view that hides the ducts leaves the air out, and one that hides the pipes the fixtures. Components in a pipe or a duct, and duct parts that name no duct, are not the room's.
13.5 Symbols
A symbol is a detail item that places a symbol of a library: a valve, a pump, a heat exchanger, a fan, a damper, as a flow schematic draws them. It is drawn at paper size, the same size on the sheet at any scale, with its fill and its texts. Its ports are the points where lines join it. Symbols are made for schematics, drawn in drafting views; a symbol may stand in any view.
A detail item of the kind symbol stands at its a, and its b is the same point. Its symbol:
| Member | Meaning | |
|---|---|---|
name | required | the symbol, by its name in the application's library: 1 to 40 characters, an application value |
rotation | optional | its turn about a, in degrees counter-clockwise, from −360 to 360; absent, 0 |
mirror | optional | true: mirrored across its own vertical axis before it is turned |
texts | optional | its texts, by the library's slots: each slot's name 1 to 20 characters, its text at most 40, such as {"tag": "P201"} |
The library is the application's. A library gives each symbol its shapes, its texts' slots and its ports, in paper mm about its insertion point, y up; OpenEik lists none (section 8, rule 3; open question 50). A point (x, y) of a symbol stands in the view at a + scale · R(rotation) · (±x, y): −x where it is mirrored, R the turn counter-clockwise, scale the view's. An application that does not know a symbol's name keeps the item, and may draw it as a box with its name.
Lines joined to ports. A line's connect joins its ends to ports: {start?, end?}, each {detailId, port}, the symbol item and the name of its port in the library (1 to 40 characters, an application value). The line's first point is its start, and its last its end.
- A joined end stands on its port. Its stored point is the port's, where the view draws it: the stored line is what is drawn.
- When a symbol moves, turns or is mirrored, or its view's scale changes, a writer moves each end joined to its ports with them.
- When an end is moved off its port, or the symbol goes, the end lets go: the writer takes it out of
connectand leaves the end where it is. - An end put on a port, within 0.6 paper mm of it, MAY be joined to it by a writer.
The line from a pump's outlet to a valve's inlet, in a schematic at the scale 1:
[
{
"a": [100, 100],
"b": [100, 100],
"color": "#000000",
"id": "pump-a",
"kind": "symbol",
"symbol": {
"name": "pump",
"texts": {
"tag": "P201"
}
}
},
{
"a": [150, 100],
"b": [150, 100],
"color": "#000000",
"id": "valve-b",
"kind": "symbol",
"symbol": {
"name": "isolatingValve"
}
},
{
"a": [104, 100],
"b": [146, 100],
"color": "#000000",
"connect": {
"end": {
"detailId": "valve-b",
"port": "in"
},
"start": {
"detailId": "pump-a",
"port": "out"
}
},
"id": "line-a",
"kind": "line"
}
]
13.6 Rules
- Each of a view's
visibility.systems.idsMUST be a system of section 6.9, alone or with a number from 1 to 99 after a colon, written without a leading zero. The schemas state this rule:^(<system>|…)(:[1-9][0-9]?)?$. - A
textFrame, adisplay.textFrameand adisplay.mepTagFrameMUST giveshape, and their members MUST be within the ranges of 13.2. AtextBackgroundMUST beopaqueortransparent. The schemas state this rule. display.mepTags,mepTagEditsanddisplay.mepTagTemplatesMUST be of the shapes of 13.3; the schemas state it, and mark each row of a template"x-eik-application": true. A reader MUST keep a template's rows unchanged, and MUST NOT need to read them: an application that does not know a template's language draws the tags as it would without it.- The element that a tag of the field
roomnames MUST be a room of the model. - A detail item of the kind
symbolMUST carrysymbol, and a detail item of another kind MUST NOT. The schemas state this rule. - A detail item of another kind than
lineMUST NOT carryconnect. The schemas state this rule. - Each
detailIdof a line'sconnectMUST name a detail item of the kindsymbolof the line's own view. - A writer MUST keep a joined end on its port, as 13.5 says, or let it go.
- A symbol's
name, a port's name and a text's slot are the application's: a validator MUST NOT refuse one because a library does not hold it, and a reader keeps them unchanged.
Reference: systemFilterSchema in src/core/views/systemFilterSchema.ts and systemFilterHides in src/core/views/systemPlans.ts (Stomra work 611), withSystemFilterIds and looseSystemIds in systemFilterSchema.ts (669); textFrameSchema, frameOf and frameBox in src/core/annotations/textFrame.ts (608); mepTagModes, mepTagEditSchema and taggedRuns in src/core/elements/mepTagSchema.ts and mepTags.ts (its work 540); viewTagTemplatesSchema in src/core/elements/mepTagTemplateSchema.ts and the filling in mepTagTemplate.ts (621); roomTagRows and roomTagPoint in src/core/elements/roomTag.ts, and tagItemSchema in src/core/sheets/tagItemSchema.ts (622); tagLineUpCommandSchema and linedUpView (623); symbolItemSchema and lineConnectSchema in src/core/sheets/symbolItemSchema.ts, the refinement of a detail item in src/core/sheets/documentation.ts (rules 5 and 6), symbolGeometry in src/core/annotations/symbolLibrary.ts, and connectedDetails and withConnectedSymbols in src/core/annotations/symbolConnections.ts (634).
14. Members of views, detail items and detail families
Part of 0.2. OpenEik 0.1 had it as the proposal adopted: in a model of 0.1, read by 0.1's rules (Part I, 9.6, rule 3), the members of this section are members a schema of 0.1 does not know, which a reader keeps (Part I, 10). The section adds them, the cut pattern clt (section 4, rule 4), the reference a bolt group's bolts.through holds (section 7), a slab edge element's notches (Part IV, 4.6, rules 12 to 14), and no file. Their schemas, in schemas/0.2/adopted/, are generated from the reference implementation's, as the schemas of 0.1 are.
By the steward's decision of 30 October 2026 (open questions, 115). The reference implementation writes these members, and another tool needs them to read, draw, check or print the building, so they join 0.2. What only the reference implementation's own interface reads, it writes under its prefix from 0.2 (Part I, 11.5).
14.1 Elements cast in one pour
- An element MAY carry
castWith, the id of another element that it is cast with in one pour, as a foundation poured with the slab on it. It SHOULD name an element of the model (section 7), and MUST NOT name the element itself: a validator warns of one that does (cast-with). - Where a section cuts both elements, their cut regions of one material, at one depth of the cut, are drawn as one region: no line is drawn where they meet, and their regions of other materials keep their lines. It changes no body and no quantity, and the two stay two elements.
14.2 A layer drawn with a detail family
A drawing of a type's build-up (a view's assembly, section 14.3, rule 4) draws each layer where it is cut, by its material's pattern (section 4).
- A layer (section 5.1) of a type of the category
slab,wall,foundation,rooforceilingMAY carrydrawing,{familyId?, typeId?, spacing?, offset?, rotation?, align?}: the detail family its cut is drawn with in such a drawing, in place of its material's pattern.familyIdSHOULD name a detail family of the model (project/detail-families), andtypeIdnames one of that family's types; a validator warns of atypeIdthe family does not have, or one without afamilyId(layer-drawing). WithoutfamilyIdthe layer draws nothing of its own where it is cut, so that what the layer beside it draws shows there, as the battens a roof's tiles hang on. - The copies. The family is drawn along the layer again and again, each copy centred on its place: at
offsetmm from the layer's start (0 where it is absent) and everyspacingmm from there, both ways, as far as a copy reaches into the layer; wherespacingis absent, the copies lie side by side, each its own extent along the layer from the next. Each copy is turned byrotationdegrees, as a detail item's rotation turns it. Across the layer it lies on the layer's middle, or, withaligninsideoroutside, its box against the layer's inside or outside face; a family with an insertion point (section 14.5) hangs by that point instead, on the layer's middle, inside or outside face. - Its axes. The family's x runs along the layer, a roof's from its eave up and a wall's from its foot up, and its y out of the building.
- A layer's drawing changes no body and no quantity.
14.3 A view
- An electrical plan's devices. A plan's
display.electricalsays which electrical devices (Part XIII, 2) it draws:power, every device but a data outlet, a TV outlet, a speaker and an access point (the kindsdataOutlet,tvOutlet,speakerandaccessPoint);data, those four kinds alone; absent, all of them. On a view of another kind it means nothing, and a validator warns of it there (adopted-kind). - Level heads.
display.levelLabels,false, draws a section's, an elevation's or a callout's level lines without their heads, the mark that gives the level's name and its elevation; absent ortrue, with them. - The sides of a build-up.
display.sideMarks,false, leaves out the marks that a drawing of a type's build-up (rule 4) sets beside its sides, outside and inside for a wall, top and underside for a horizontal type; absent ortrue, they are drawn. Their words are the drawing application's. - A build-up's pitch. A view's
assembly,{typeId, mode}in 0.1, draws the build-up of the typetypeIdnames: cut vertically (vertical), horizontally (horizontal), or as an isometric (isometric). Itspitch, from 0 to 75 degrees, is the pitch a roof type's vertical cut is drawn at, turned about its middle and rising to the right. Absent, it is the pitch every roof of the type has, the slope of its first slope-defining edge to 0.1 degrees (0 for a roof without one), where they all have the same, else 0, level. - Line weights. A view's
lineWeights,true, says that the view is drawn on screen with its line weights; absent, it is drawn in thin lines, every line one device pixel wide. It is the view's own, so that it is the same for everyone who opens the view. A print draws a view's line weights whatever it says. - A 3D view's perspective camera. A 3D view MAY carry
camera,{position, target, fov}: where its perspective camera stands and the point it looks at, each[x, y, z]in mm in the model's axes, and its vertical field of view in degrees, from 10 to 120.positionandtargetMUST be at least 1 mm apart; a validator reports a camera whose two points are not (camera-points). A tool that shows the view in perspective, or renders it, looks so. A sheet draws a 3D view without perspective, by the camera of itsorigin,directionandaxonometricElevation, whichcameraleaves as they are, so a 3D view that a sheet places SHOULD NOT carrycamera. On a view of another kind it means nothing (adopted-kind).
14.4 Detail items
- A revision cloud. A detail item of the kind
lineMAY carrycloud,{arc, inward?, revision?, tag?, tagHidden?}, which draws it as a revision cloud. Its points (itspoints, elseaandb) are the cloud's corners, in order round it, and it is closed. Between them it is drawn as scallops ofarcmm on the paper, from 1 to 50, so that they keep their size at any scale, bulging out of the cloud, or into it whereinwardistrue.revision, at most 20 characters, is the mark of the revision the cloud belongs to, which its tag shows: a triangle with the mark in it, centred ontag, a point of the view, else on the cloud's first corner. The tag is not drawn wheretagHiddenistrueor the mark is empty. A reader that does not draw clouds draws the corners as a closed line. On an item of another kindcloudmeans nothing (adopted-kind). - A schedule's headings. A schedule's
schedule.headingsgives its columns' headings by the field each column shows (number,name,areaand the others its schema names), each of 1 to 80 characters, in place of the headings the drawing application gives them; a column whose field it does not name keeps the application's. - A legend's heading. A legend's
legend.title, of 1 to 120 characters, is its own heading, in place of the one the drawing application gives its scheme. - A build-up text. A detail item of the kind
leaderMAY carrybuildUp,{typeId, uValue?}, which makes its text the build-up of the typetypeIdnames: a line for each of its layers, in the order of section 5.1, rule 6, a wall's exterior first and a horizontal type's top first, each with its thickness and its name; and above them the type's U value (section 5.5), unlessuValueisfalse. The text is worked out from the type each time it is drawn, so that it follows the type; its words and its layout are the drawing application's. Where the item gives its owntext, that text is drawn instead.typeIdSHOULD name a type of the model that has layers: a validator warns of a type without (build-up-type). On an item of another kindbuildUpmeans nothing (adopted-kind). - An item that follows a group's instance. A detail item of a plan MAY carry
follows, the mark of the instance of a group (section 10) it moves and turns with: the id of a copy, or of an original whose kept elements are its own instance (itsframeabsent or its own id). Only a free item follows an instance: neither a tag, a view reference, a schedule or a legend, nor an item withtag,dimensionReferences,hatchHost,hostormodelPoint, each of which follows what it is tied to. On such an item, or on an item of a view that is no plan,followsis not read, and a validator warns of it (follows-free). It SHOULD name an instance of the model. - Moving with it. A command that moves or turns an instance (
copy.move, Part V, 2.1) moves and turns the items that follow it, as its elements move: each is turned by the change of the instance'sturnabout the point itsatnamed before, then moved by the change of itsat. Where the instance goes (copy.remove,copy.unique,original.dissolve), an item that follows it stays where it is, and the command takes itsfollowsaway. - A region cut by groups. A detail item of the kind
regionin a plan MAY carrycutBy, 1 to 200 marks of instances of groups (rule 5), whose floors are taken out of it where it is drawn. An instance's floors are, in plan, the outlines of its slabs and foundations on the plan's level; where it has none there, those on the lowest level it has any on; where it has none at all, the convex hull of what it covers in plan. They are worked out where the instance stands each time the region is drawn, so that a hole moves with its instance. The region keeps its own outline, and is drawn as that outline less theirs. Each mark SHOULD name an instance of the model; where an instance goes, its mark is taken out ofcutBy, and its hole closes. On an item of another kindcutBymeans nothing (adopted-kind). - A text that measures nothing. A detail item of the kind
textMAY carrynotDimension,true: its words read as a number, and measure nothing, so that a check that holds a drawing's written dimensions to the model leaves it out. An item of another kind MUST NOT carry it (not-dimension).
14.5 A detail family's insertion point
- A detail family MAY carry
insertion,[x, y], the point of the family that a placed copy hangs on: a single item of the family at its place, each copy of a repeating detail along its path, each copy of a layer's drawing (section 14.2). Each of the two is in the family's own mm, a number or bound to its parameters as a sketch's points are ({parameter, factor?, offset?}or{terms, offset?}); a parameter it names MUST be one of the family's (insertion-parameter). Withoutinsertion, a single item hangs on the family's origin, and a repeated copy on the middle of its box, so that an edit that changes the box moves the repeated copies; with it, an edit never does.
14.6 A terminal's tag without its size
- A terminal type's
terminal.tagSize,false, says that its elements' tags give no size: the plan's automatic tags and a template'ssizefield (section 13.3). Absent ortrue, they give the size of the type's connection of the terminal's own system, else of its first connection. A component in a pipe or a duct (section 6.9) is tagged with its run's size whatever its type says.
Reference: castGroups in src/core/geometry/sectionOutline.ts (Stomra work 508); layerDrawingSchema and layerCopies in src/core/assemblies/layerDrawing.ts, roofTypePitch in assemblyViews.ts, and buildUpSchema and buildUpText in src/core/sheets/buildUpSchema.ts and src/core/assemblies/buildUpText.ts (its work 556); viewElectrical in src/core/views/viewVisibility.ts and electricalPart in src/core/elements/electrical.ts (537); levelLabels and sideMarks in a view's display (651); lineWeights in viewSchema of src/core/model/model.ts (706); perspectiveCameraSchema in src/core/views/perspectiveSchema.ts and perspectiveOf in perspectiveCamera.ts (747); revisionCloudSchema and cloudTag in src/core/annotations/revisionCloudSchema.ts and revisionCloud.ts (523); canFollow and moveFollowers in src/core/model/groupDetails.ts (603); instanceFloors in src/core/annotations/regionCuts.ts (678); the refinement of a detail item in src/core/sheets/documentation.ts (notDimension, 695); familyAnchor in src/core/annotations/detailFamilies.ts (556); tagSize in terminalTypeSchema and terminalTag in src/core/elements/mep.ts (543).