IFC Syntax : Data Types
This skill answers one concrete question : what can the value of an IFC attribute or
property hold, and how is that value typed in a file? It covers IFC's own resource-
layer value-type system : the named defined types (IfcLengthMeasure, IfcLabel,
IfcBoolean, ...) and the SELECT unions that group them.
Applies to IFC2x3, IFC4, and IFC4.3. Member lists differ by version : see the
Version Differences section.
Quick Reference
Two type systems : keep them apart
IFC has two layered type systems. ALWAYS keep them separate :
- The EXPRESS meta-language (
ifc-syntax-express) : the constructs TYPE,
ENTITY, SELECT, ENUMERATION, the base types STRING, REAL, INTEGER,
BOOLEAN, LOGICAL, BINARY, NUMBER. These are the blocks the schema is
written with.
- IFC's own value-type system (this skill) : the named defined types IFC
declares on top of those base types, plus the
SELECT unions that group them.
IFC wraps every base type in a named defined type because an EXPRESS SELECT may
list only named types, NEVER raw BOOLEAN / REAL / INTEGER. That is why
TYPE IfcBoolean = BOOLEAN;, TYPE IfcReal = REAL;, and TYPE IfcInteger = INTEGER;
exist : so they can be members of a select.
IfcValue : the two-level union
IfcValue is the most general value type in IFC. It is the declared type of
IfcPropertySingleValue.NominalValue and of IfcMeasureWithUnit.ValueComponent.
Verified verbatim (IFC4.3, introduced IFC2x) :
TYPE IfcValue = SELECT
(IfcDerivedMeasureValue
,IfcMeasureValue
,IfcSimpleValue);
END_TYPE;
IfcValue is a SELECT whose three members are themselves SELECT types : a
two-level union. A parser resolving an IfcValue descends through one branch to
reach a concrete defined type.
| Branch |
Holds |
Has a unit? |
IfcSimpleValue |
primitive, dimensionless values : booleans, integers, reals, strings, logicals, dates, binary |
No |
IfcMeasureValue |
base physical measures : length, area, volume, angle, mass, count, ratio |
Yes (single SI dimension) |
IfcDerivedMeasureValue |
compound measures : force, pressure, velocity, density, thermal transmittance, money |
Yes (derived SI dimension) |
IfcSimpleValue members (IFC4.3 : 15 members)
| Type |
Base |
Use for |
IfcBoolean |
BOOLEAN |
a known two-valued yes/no fact |
IfcLogical |
LOGICAL |
a fact that may also be UNKNOWN |
IfcInteger |
INTEGER |
whole numbers |
IfcPositiveInteger |
INTEGER, SELF > 0 |
strictly positive whole numbers (IFC4+) |
IfcReal |
REAL |
dimensionless real numbers |
IfcLabel |
STRING(255) |
a human-readable name |
IfcText |
STRING (unbounded) |
free-form description / note |
IfcIdentifier |
STRING(255) |
a machine-readable code / key |
IfcBinary |
BINARY |
embedded binary data, for example textures (IFC4 ADD1+) |
IfcDateTime |
STRING, ISO 8601 |
date and time (IFC4+) |
IfcDate |
STRING, ISO 8601 |
calendar date (IFC4+) |
IfcTime |
STRING, ISO 8601 |
time of day (IFC4+) |
IfcDuration |
STRING, ISO 8601 |
a duration (IFC4+) |
IfcTimeStamp |
INTEGER |
seconds since the Unix epoch |
IfcURIReference |
STRING |
a URI / URL / URN (IFC4+) |
IfcMeasureValue : high-frequency base measures (IFC4.3 : 23 members)
| Measure type |
Base |
Unit type implied |
IfcLengthMeasure |
REAL |
LENGTHUNIT |
IfcPositiveLengthMeasure |
IfcLengthMeasure, SELF > 0 |
LENGTHUNIT |
IfcNonNegativeLengthMeasure |
IfcLengthMeasure, SELF >= 0 (IFC4+) |
LENGTHUNIT |
IfcAreaMeasure |
REAL |
AREAUNIT |
IfcVolumeMeasure |
REAL |
VOLUMEUNIT |
IfcPlaneAngleMeasure |
REAL |
PLANEANGLEUNIT |
IfcMassMeasure |
REAL |
MASSUNIT |
IfcCountMeasure |
INTEGER (IFC4.3 ; NUMBER before) |
not a unit type |
IfcRatioMeasure |
REAL |
dimensionless |
IfcNormalisedRatioMeasure |
IfcRatioMeasure, 0.0 <= SELF <= 1.0 |
dimensionless |
Full 23-member list : see references/methods.md.
IfcDerivedMeasureValue : high-frequency derived measures (IFC4.3 : 70 members)
| Measure type |
Base |
Notes |
IfcForceMeasure |
REAL |
force |
IfcPressureMeasure |
REAL |
pressure |
IfcLinearVelocityMeasure |
REAL |
velocity |
IfcMassDensityMeasure |
REAL |
density |
IfcThermalTransmittanceMeasure |
REAL |
U-value |
IfcMonetaryMeasure |
REAL |
money, currency-agnostic |
IfcCompoundPlaneAngleMeasure |
LIST [3:4] OF INTEGER |
degrees / minutes / seconds, NOT a scalar |
Full 70-member list : see references/methods.md.
Typed-value wrapping in a STEP file
A value whose attribute is declared with a concrete type is written bare :
'Wall-01' for an IfcLabel-typed Name.
A value whose attribute is declared as a SELECT (such as IfcValue) MUST be
wrapped in the upper-cased name of the concrete member type, so the reader knows
which branch was chosen :
#101=IFCPROPERTYSINGLEVALUE('FireRating',$,IFCLABEL('REI 60'),$);
#102=IFCPROPERTYSINGLEVALUE('NetArea',$,IFCAREAMEASURE(12.5),$);
#103=IFCPROPERTYSINGLEVALUE('LoadBearing',$,IFCBOOLEAN(.T.),$);
The wrapper name IS the type tag. NEVER write a bare value where a select type is
expected : the reader cannot tell 12.5 apart as an area, a length, or a plain real.
Version differences (compact)
| Item |
IFC2x3 |
IFC4 |
IFC4.3 |
IfcSimpleValue members |
7 |
15 |
15 |
IfcDateTime, IfcDate, IfcTime, IfcDuration, IfcBinary, IfcPositiveInteger, IfcURIReference |
absent |
present |
present |
IfcCountMeasure base type |
NUMBER |
NUMBER |
INTEGER |
IfcNonNegativeLengthMeasure |
absent |
present |
present |
IfcLabel / IfcIdentifier 255 cap |
recommended |
mandatory |
mandatory |
Decision Trees
Which value type for a property value?
What does the value represent?
|
+-- A physical quantity with a single SI dimension
| (length, area, volume, angle, mass, ratio, count)
| --> IfcMeasureValue branch. Pick the measure type whose
| dimension matches : IfcLengthMeasure, IfcAreaMeasure, ...
|
+-- A compound physical quantity
| (force, pressure, velocity, density, U-value, money)
| --> IfcDerivedMeasureValue branch.
| IfcForceMeasure, IfcPressureMeasure, IfcMonetaryMeasure, ...
|
+-- A non-physical, dimensionless value
(text, name, code, yes/no, count of items, date, real number)
--> IfcSimpleValue branch. IfcLabel, IfcText, IfcBoolean, ...
IfcBoolean or IfcLogical?
Can the attribute meaningfully be "unknown / not applicable",
distinct from FALSE?
|
+-- NO : it is always a known yes/no fact
| --> IfcBoolean (.T. / .F.)
|
+-- YES : "not known" is a real third state
--> IfcLogical (.T. / .F. / .U.)
NEVER substitute IfcBoolean for a schema-declared IfcLogical :
that collapses UNKNOWN into FALSE and loses information.
A present .U. is NOT the same as an absent $ (unset OPTIONAL).
IfcLabel, IfcText, or IfcIdentifier?
What is the string for?
|
+-- A short, human-readable display NAME
| --> IfcLabel (STRING(255))
|
+-- A machine-readable CODE / KEY, stable and locale-independent
| (classification code, part number)
| --> IfcIdentifier (STRING(255))
|
+-- Free-form descriptive prose, a note, possibly long
--> IfcText (unbounded STRING)
IfcLabel and IfcIdentifier are byte-identical (STRING(255)) but
NEVER interchangeable in intent : the schema picks one deliberately.
Which measure type for a quantity?
Match the measure type to the physical SI dimension :
|
+-- a distance --> IfcLengthMeasure
+-- a distance, > 0 --> IfcPositiveLengthMeasure
+-- a distance, >= 0 --> IfcNonNegativeLengthMeasure (IFC4+)
+-- a surface area --> IfcAreaMeasure
+-- a volume --> IfcVolumeMeasure
+-- a planar angle --> IfcPlaneAngleMeasure
+-- a latitude/longitude--> IfcCompoundPlaneAngleMeasure (deg/min/sec list)
+-- a mass --> IfcMassMeasure
+-- a count of items --> IfcCountMeasure
+-- a same-kind ratio --> IfcRatioMeasure (percent / 100)
+-- a ratio in [0,1] --> IfcNormalisedRatioMeasure
NEVER pick by what parses : an area stored as IfcLengthMeasure
parses fine and resolves to the wrong project unit.
Patterns
Pattern : Wrap select-typed values
ALWAYS wrap a value as TYPENAME(value) when the attribute is declared as a SELECT
(such as IfcValue, IfcSizeSelect, IfcUnit). The wrapper is the discriminator.
ALWAYS write a value bare when the attribute is declared with a concrete defined type :
IfcRoot.Name is IfcLabel, so 'Wall-01' is written bare.
NEVER write a bare numeric or string value into a select-typed attribute : the reader
has no way to know which select member it is, and the file is malformed.
See ifc-syntax-step-physical-file for the full STEP instance syntax.
Pattern : Pick the measure type by SI dimension
ALWAYS choose the measure type whose physical dimension matches the quantity : a
length is IfcLengthMeasure, an area is IfcAreaMeasure, a volume is
IfcVolumeMeasure, an angle is IfcPlaneAngleMeasure.
The measure type, NOT the number, selects the unit. An IfcLengthMeasure of 3.5
means 3.5 of the project length unit. A wall area stored as IfcLengthMeasure
resolves against LENGTHUNIT instead of AREAUNIT and silently corrupts every
downstream quantity take-off.
NEVER decide a measure type by whether the value parses : every measure type is
ultimately a REAL, so a wrong type always parses.
See ifc-syntax-units for how a unit type resolves to a concrete unit.
Pattern : Choose two-valued vs three-valued logic
ALWAYS use IfcLogical when "unknown" or "not applicable" is a meaningful state
distinct from FALSE. The canonical case is IfcMaterialLayer.IsVentilated, an
OPTIONAL IfcLogical : TRUE is a ventilated air gap, FALSE is solid material,
UNKNOWN is a non-ventilated air gap.
ALWAYS use IfcBoolean when the attribute is a yes/no fact that is always known.
NEVER treat a present IfcLogical value of .U. (UNKNOWN) as equivalent to an
absent OPTIONAL attribute ($) : $ means no value was supplied, .U. means a
value was supplied and it is the third logical state.
Pattern : Pair USERDEFINED with ObjectType
Almost every IFC PredefinedType enumeration (for example IfcWallTypeEnum) ends
with two special members : USERDEFINED and NOTDEFINED. NOTDEFINED means no
predefined type applies. USERDEFINED means a type outside the fixed list.
ALWAYS supply the paired free-text type name when PredefinedType = USERDEFINED :
on an occurrence object, in IfcObject.ObjectType (an IfcLabel) ; on a type
object, in IfcElementType.ElementType. An entity WHERE rule (for example
IfcWall.CorrectPredefinedType) enforces this pairing.
NEVER set PredefinedType = USERDEFINED and leave the paired attribute unset : the
file violates the WHERE rule and is schema-invalid.
An enumeration value is NOT an IfcValue. IfcValue covers user-supplied data
values ; a PredefinedType is a schema-fixed classification token. They are
different layers. See ifc-syntax-express for the ENUMERATION construct.
Pattern : Respect refinement WHERE rules
The Positive*, NonNegative*, and Normalised* types are NOT separate primitive
types : they are defined types layered on a base measure with an added WHERE rule.
| Type |
Base |
WHERE rule |
IfcPositiveLengthMeasure |
IfcLengthMeasure |
SELF > 0. |
IfcNonNegativeLengthMeasure |
IfcLengthMeasure |
SELF >= 0. |
IfcPositivePlaneAngleMeasure |
IfcPlaneAngleMeasure |
SELF > 0. |
IfcPositiveRatioMeasure |
IfcRatioMeasure |
SELF > 0. |
IfcNormalisedRatioMeasure |
IfcRatioMeasure |
{0.0 <= SELF <= 1.0} |
ALWAYS check the refinement's WHERE rule before assigning : 0.0 or a negative
value in an IfcPositiveLengthMeasure parses as a plain real but is schema-invalid.
NEVER assume a value that parses satisfies the type : the WHERE rule is part of the
type.
Pattern : Honour version differences
ALWAYS target the member list for the file's declared schema version :
- In IFC2x3,
IfcSimpleValue has only 7 members. NEVER emit IfcDateTime,
IfcDate, IfcTime, IfcDuration, IfcBinary, IfcPositiveInteger, or
IfcURIReference as an IfcValue payload in an IFC2x3 file : IFC2x3 uses
structured date entities (IfcCalendarDate, IfcLocalTime, IfcDateAndTime).
- In IFC4.3,
IfcCountMeasure is an INTEGER. A non-integer count is valid
IFC4 but invalid IFC4.3. ALWAYS use whole numbers for IfcCountMeasure in IFC4.3.
- The
IfcLabel / IfcIdentifier 255-character cap was advisory before IFC4 and
mandatory from IFC4 onward.
See references/methods.md for the complete per-version member tables.
Reference Links
references/methods.md : the complete verified member lists : IfcSimpleValue
(15 + the IFC2x3 7), the full 23-member IfcMeasureValue select, the full
70-member IfcDerivedMeasureValue select, every base definition, the measure-to-
unit-type mapping, and the per-version difference tables.
references/examples.md : worked scenarios : typing a property value, reading a
wrapped STEP value, choosing between string types, USERDEFINED pairing,
IFC2x3-vs-IFC4 value typing.
references/anti-patterns.md : the failure modes this skill prevents, each with
the reason it fails.
Official sources
Related skills
ifc-syntax-express : the EXPRESS meta-language : TYPE, SELECT, ENUMERATION,
WHERE, the base types this skill's defined types are built on.
ifc-syntax-units : how a measure type's unit type resolves to a concrete unit
via IfcUnitAssignment.
ifc-syntax-property-sets : where IfcValue-typed property values are carried.
1---2name: ifc-syntax-data-types3description: Use when you need to pick or read the value type of an IFC attribute or property : which measure type a length, area, or volume needs, when to use IfcLabel vs IfcText vs IfcIdentifier, IfcBoolean vs IfcLogical, and how a typed value is wrapped in a STEP file. Prevents storing a quantity under the wrong measure type, exceeding the 255-character string cap, collapsing a three-valued logical into a boolean, and writing a bare value where a select type requires a TYPENAME() wrapper. Covers the IfcValue / IfcSimpleValue / IfcMeasureValue / IfcDerivedMeasureValue select hierarchy, the measure types, string and identity types, the USERDEFINED / NOTDEFINED enumeration convention, refinement WHERE rules, and IFC2x3 / IFC4 / IFC4.3 version differences. Keywords: IFC data types, IfcValue, IfcSimpleValue, IfcMeasureValue, IfcDerivedMeasureValue, IfcLengthMeasure, IfcAreaMeasure, IfcVolumeMeasure, IfcLabel, IfcText, IfcIdentifier, IfcBoolean, IfcLogical, measure type, typed value wrapping, USERDEFINED, NOTDEFINED, ObjectT4license: MIT5---67# IFC Syntax : Data Types89This skill answers one concrete question : what can the value of an IFC attribute or10property hold, and how is that value typed in a file? It covers IFC's own resource-11layer value-type system : the named defined types (`IfcLengthMeasure`, `IfcLabel`,12`IfcBoolean`, ...) and the `SELECT` unions that group them.1314Applies to IFC2x3, IFC4, and IFC4.3. Member lists differ by version : see the15Version Differences section.1617## Quick Reference1819### Two type systems : keep them apart2021IFC has two layered type systems. ALWAYS keep them separate :22231. **The EXPRESS meta-language** (`ifc-syntax-express`) : the constructs `TYPE`,24 `ENTITY`, `SELECT`, `ENUMERATION`, the base types `STRING`, `REAL`, `INTEGER`,25 `BOOLEAN`, `LOGICAL`, `BINARY`, `NUMBER`. These are the blocks the schema is26 written with.272. **IFC's own value-type system** (this skill) : the named defined types IFC28 declares on top of those base types, plus the `SELECT` unions that group them.2930IFC wraps every base type in a named defined type because an EXPRESS `SELECT` may31list only named types, NEVER raw `BOOLEAN` / `REAL` / `INTEGER`. That is why32`TYPE IfcBoolean = BOOLEAN;`, `TYPE IfcReal = REAL;`, and `TYPE IfcInteger = INTEGER;`33exist : so they can be members of a select.3435### IfcValue : the two-level union3637`IfcValue` is the most general value type in IFC. It is the declared type of38`IfcPropertySingleValue.NominalValue` and of `IfcMeasureWithUnit.ValueComponent`.39Verified verbatim (IFC4.3, introduced IFC2x) :4041```42TYPE IfcValue = SELECT43 (IfcDerivedMeasureValue44 ,IfcMeasureValue45 ,IfcSimpleValue);46END_TYPE;47```4849`IfcValue` is a `SELECT` whose three members are themselves `SELECT` types : a50two-level union. A parser resolving an `IfcValue` descends through one branch to51reach a concrete defined type.5253| Branch | Holds | Has a unit? |54|--------|-------|-------------|55| `IfcSimpleValue` | primitive, dimensionless values : booleans, integers, reals, strings, logicals, dates, binary | No |56| `IfcMeasureValue` | base physical measures : length, area, volume, angle, mass, count, ratio | Yes (single SI dimension) |57| `IfcDerivedMeasureValue` | compound measures : force, pressure, velocity, density, thermal transmittance, money | Yes (derived SI dimension) |5859### IfcSimpleValue members (IFC4.3 : 15 members)6061| Type | Base | Use for |62|------|------|---------|63| `IfcBoolean` | `BOOLEAN` | a known two-valued yes/no fact |64| `IfcLogical` | `LOGICAL` | a fact that may also be UNKNOWN |65| `IfcInteger` | `INTEGER` | whole numbers |66| `IfcPositiveInteger` | `INTEGER`, `SELF > 0` | strictly positive whole numbers (IFC4+) |67| `IfcReal` | `REAL` | dimensionless real numbers |68| `IfcLabel` | `STRING(255)` | a human-readable name |69| `IfcText` | `STRING` (unbounded) | free-form description / note |70| `IfcIdentifier` | `STRING(255)` | a machine-readable code / key |71| `IfcBinary` | `BINARY` | embedded binary data, for example textures (IFC4 ADD1+) |72| `IfcDateTime` | `STRING`, ISO 8601 | date and time (IFC4+) |73| `IfcDate` | `STRING`, ISO 8601 | calendar date (IFC4+) |74| `IfcTime` | `STRING`, ISO 8601 | time of day (IFC4+) |75| `IfcDuration` | `STRING`, ISO 8601 | a duration (IFC4+) |76| `IfcTimeStamp` | `INTEGER` | seconds since the Unix epoch |77| `IfcURIReference` | `STRING` | a URI / URL / URN (IFC4+) |7879### IfcMeasureValue : high-frequency base measures (IFC4.3 : 23 members)8081| Measure type | Base | Unit type implied |82|--------------|------|-------------------|83| `IfcLengthMeasure` | `REAL` | `LENGTHUNIT` |84| `IfcPositiveLengthMeasure` | `IfcLengthMeasure`, `SELF > 0` | `LENGTHUNIT` |85| `IfcNonNegativeLengthMeasure` | `IfcLengthMeasure`, `SELF >= 0` (IFC4+) | `LENGTHUNIT` |86| `IfcAreaMeasure` | `REAL` | `AREAUNIT` |87| `IfcVolumeMeasure` | `REAL` | `VOLUMEUNIT` |88| `IfcPlaneAngleMeasure` | `REAL` | `PLANEANGLEUNIT` |89| `IfcMassMeasure` | `REAL` | `MASSUNIT` |90| `IfcCountMeasure` | `INTEGER` (IFC4.3 ; `NUMBER` before) | `not a unit type` |91| `IfcRatioMeasure` | `REAL` | dimensionless |92| `IfcNormalisedRatioMeasure` | `IfcRatioMeasure`, `0.0 <= SELF <= 1.0` | dimensionless |9394Full 23-member list : see `references/methods.md`.9596### IfcDerivedMeasureValue : high-frequency derived measures (IFC4.3 : 70 members)9798| Measure type | Base | Notes |99|--------------|------|-------|100| `IfcForceMeasure` | `REAL` | force |101| `IfcPressureMeasure` | `REAL` | pressure |102| `IfcLinearVelocityMeasure` | `REAL` | velocity |103| `IfcMassDensityMeasure` | `REAL` | density |104| `IfcThermalTransmittanceMeasure` | `REAL` | U-value |105| `IfcMonetaryMeasure` | `REAL` | money, currency-agnostic |106| `IfcCompoundPlaneAngleMeasure` | `LIST [3:4] OF INTEGER` | degrees / minutes / seconds, NOT a scalar |107108Full 70-member list : see `references/methods.md`.109110### Typed-value wrapping in a STEP file111112A value whose attribute is declared with a **concrete** type is written **bare** :113`'Wall-01'` for an `IfcLabel`-typed `Name`.114115A value whose attribute is declared as a **`SELECT`** (such as `IfcValue`) MUST be116**wrapped** in the upper-cased name of the concrete member type, so the reader knows117which branch was chosen :118119```120#101=IFCPROPERTYSINGLEVALUE('FireRating',$,IFCLABEL('REI 60'),$);121#102=IFCPROPERTYSINGLEVALUE('NetArea',$,IFCAREAMEASURE(12.5),$);122#103=IFCPROPERTYSINGLEVALUE('LoadBearing',$,IFCBOOLEAN(.T.),$);123```124125The wrapper name IS the type tag. NEVER write a bare value where a select type is126expected : the reader cannot tell `12.5` apart as an area, a length, or a plain real.127128### Version differences (compact)129130| Item | IFC2x3 | IFC4 | IFC4.3 |131|------|--------|------|--------|132| `IfcSimpleValue` members | 7 | 15 | 15 |133| `IfcDateTime`, `IfcDate`, `IfcTime`, `IfcDuration`, `IfcBinary`, `IfcPositiveInteger`, `IfcURIReference` | absent | present | present |134| `IfcCountMeasure` base type | `NUMBER` | `NUMBER` | `INTEGER` |135| `IfcNonNegativeLengthMeasure` | absent | present | present |136| `IfcLabel` / `IfcIdentifier` 255 cap | recommended | mandatory | mandatory |137138## Decision Trees139140### Which value type for a property value?141142```143What does the value represent?144|145+-- A physical quantity with a single SI dimension146| (length, area, volume, angle, mass, ratio, count)147| --> IfcMeasureValue branch. Pick the measure type whose148| dimension matches : IfcLengthMeasure, IfcAreaMeasure, ...149|150+-- A compound physical quantity151| (force, pressure, velocity, density, U-value, money)152| --> IfcDerivedMeasureValue branch.153| IfcForceMeasure, IfcPressureMeasure, IfcMonetaryMeasure, ...154|155+-- A non-physical, dimensionless value156 (text, name, code, yes/no, count of items, date, real number)157 --> IfcSimpleValue branch. IfcLabel, IfcText, IfcBoolean, ...158```159160### IfcBoolean or IfcLogical?161162```163Can the attribute meaningfully be "unknown / not applicable",164distinct from FALSE?165|166+-- NO : it is always a known yes/no fact167| --> IfcBoolean (.T. / .F.)168|169+-- YES : "not known" is a real third state170 --> IfcLogical (.T. / .F. / .U.)171172NEVER substitute IfcBoolean for a schema-declared IfcLogical :173that collapses UNKNOWN into FALSE and loses information.174A present .U. is NOT the same as an absent $ (unset OPTIONAL).175```176177### IfcLabel, IfcText, or IfcIdentifier?178179```180What is the string for?181|182+-- A short, human-readable display NAME183| --> IfcLabel (STRING(255))184|185+-- A machine-readable CODE / KEY, stable and locale-independent186| (classification code, part number)187| --> IfcIdentifier (STRING(255))188|189+-- Free-form descriptive prose, a note, possibly long190 --> IfcText (unbounded STRING)191192IfcLabel and IfcIdentifier are byte-identical (STRING(255)) but193NEVER interchangeable in intent : the schema picks one deliberately.194```195196### Which measure type for a quantity?197198```199Match the measure type to the physical SI dimension :200|201+-- a distance --> IfcLengthMeasure202+-- a distance, > 0 --> IfcPositiveLengthMeasure203+-- a distance, >= 0 --> IfcNonNegativeLengthMeasure (IFC4+)204+-- a surface area --> IfcAreaMeasure205+-- a volume --> IfcVolumeMeasure206+-- a planar angle --> IfcPlaneAngleMeasure207+-- a latitude/longitude--> IfcCompoundPlaneAngleMeasure (deg/min/sec list)208+-- a mass --> IfcMassMeasure209+-- a count of items --> IfcCountMeasure210+-- a same-kind ratio --> IfcRatioMeasure (percent / 100)211+-- a ratio in [0,1] --> IfcNormalisedRatioMeasure212213NEVER pick by what parses : an area stored as IfcLengthMeasure214parses fine and resolves to the wrong project unit.215```216217## Patterns218219### Pattern : Wrap select-typed values220221ALWAYS wrap a value as `TYPENAME(value)` when the attribute is declared as a `SELECT`222(such as `IfcValue`, `IfcSizeSelect`, `IfcUnit`). The wrapper is the discriminator.223ALWAYS write a value bare when the attribute is declared with a concrete defined type :224`IfcRoot.Name` is `IfcLabel`, so `'Wall-01'` is written bare.225NEVER write a bare numeric or string value into a select-typed attribute : the reader226has no way to know which select member it is, and the file is malformed.227228See `ifc-syntax-step-physical-file` for the full STEP instance syntax.229230### Pattern : Pick the measure type by SI dimension231232ALWAYS choose the measure type whose physical dimension matches the quantity : a233length is `IfcLengthMeasure`, an area is `IfcAreaMeasure`, a volume is234`IfcVolumeMeasure`, an angle is `IfcPlaneAngleMeasure`.235The measure type, NOT the number, selects the unit. An `IfcLengthMeasure` of `3.5`236means 3.5 of the project length unit. A wall area stored as `IfcLengthMeasure`237resolves against `LENGTHUNIT` instead of `AREAUNIT` and silently corrupts every238downstream quantity take-off.239NEVER decide a measure type by whether the value parses : every measure type is240ultimately a `REAL`, so a wrong type always parses.241242See `ifc-syntax-units` for how a unit type resolves to a concrete unit.243244### Pattern : Choose two-valued vs three-valued logic245246ALWAYS use `IfcLogical` when "unknown" or "not applicable" is a meaningful state247distinct from `FALSE`. The canonical case is `IfcMaterialLayer.IsVentilated`, an248`OPTIONAL IfcLogical` : `TRUE` is a ventilated air gap, `FALSE` is solid material,249`UNKNOWN` is a non-ventilated air gap.250ALWAYS use `IfcBoolean` when the attribute is a yes/no fact that is always known.251NEVER treat a present `IfcLogical` value of `.U.` (UNKNOWN) as equivalent to an252absent `OPTIONAL` attribute (`$`) : `$` means no value was supplied, `.U.` means a253value was supplied and it is the third logical state.254255### Pattern : Pair USERDEFINED with ObjectType256257Almost every IFC `PredefinedType` enumeration (for example `IfcWallTypeEnum`) ends258with two special members : `USERDEFINED` and `NOTDEFINED`. `NOTDEFINED` means no259predefined type applies. `USERDEFINED` means a type outside the fixed list.260261ALWAYS supply the paired free-text type name when `PredefinedType = USERDEFINED` :262on an occurrence object, in `IfcObject.ObjectType` (an `IfcLabel`) ; on a type263object, in `IfcElementType.ElementType`. An entity `WHERE` rule (for example264`IfcWall.CorrectPredefinedType`) enforces this pairing.265NEVER set `PredefinedType = USERDEFINED` and leave the paired attribute unset : the266file violates the `WHERE` rule and is schema-invalid.267268An enumeration value is NOT an `IfcValue`. `IfcValue` covers user-supplied data269values ; a `PredefinedType` is a schema-fixed classification token. They are270different layers. See `ifc-syntax-express` for the `ENUMERATION` construct.271272### Pattern : Respect refinement WHERE rules273274The `Positive*`, `NonNegative*`, and `Normalised*` types are NOT separate primitive275types : they are defined types layered on a base measure with an added `WHERE` rule.276277| Type | Base | WHERE rule |278|------|------|------------|279| `IfcPositiveLengthMeasure` | `IfcLengthMeasure` | `SELF > 0.` |280| `IfcNonNegativeLengthMeasure` | `IfcLengthMeasure` | `SELF >= 0.` |281| `IfcPositivePlaneAngleMeasure` | `IfcPlaneAngleMeasure` | `SELF > 0.` |282| `IfcPositiveRatioMeasure` | `IfcRatioMeasure` | `SELF > 0.` |283| `IfcNormalisedRatioMeasure` | `IfcRatioMeasure` | `{0.0 <= SELF <= 1.0}` |284285ALWAYS check the refinement's `WHERE` rule before assigning : `0.0` or a negative286value in an `IfcPositiveLengthMeasure` parses as a plain real but is schema-invalid.287NEVER assume a value that parses satisfies the type : the `WHERE` rule is part of the288type.289290### Pattern : Honour version differences291292ALWAYS target the member list for the file's declared schema version :293294- In **IFC2x3**, `IfcSimpleValue` has only 7 members. NEVER emit `IfcDateTime`,295 `IfcDate`, `IfcTime`, `IfcDuration`, `IfcBinary`, `IfcPositiveInteger`, or296 `IfcURIReference` as an `IfcValue` payload in an IFC2x3 file : IFC2x3 uses297 structured date entities (`IfcCalendarDate`, `IfcLocalTime`, `IfcDateAndTime`).298- In **IFC4.3**, `IfcCountMeasure` is an `INTEGER`. A non-integer count is valid299 IFC4 but invalid IFC4.3. ALWAYS use whole numbers for `IfcCountMeasure` in IFC4.3.300- The `IfcLabel` / `IfcIdentifier` 255-character cap was advisory before IFC4 and301 mandatory from IFC4 onward.302303See `references/methods.md` for the complete per-version member tables.304305## Reference Links306307- `references/methods.md` : the complete verified member lists : `IfcSimpleValue`308 (15 + the IFC2x3 7), the full 23-member `IfcMeasureValue` select, the full309 70-member `IfcDerivedMeasureValue` select, every base definition, the measure-to-310 unit-type mapping, and the per-version difference tables.311- `references/examples.md` : worked scenarios : typing a property value, reading a312 wrapped STEP value, choosing between string types, USERDEFINED pairing,313 IFC2x3-vs-IFC4 value typing.314- `references/anti-patterns.md` : the failure modes this skill prevents, each with315 the reason it fails.316317### Official sources318319- IfcValue : https://ifc43-docs.standards.buildingsmart.org/IFC/RELEASE/IFC4x3/HTML/lexical/IfcValue.htm320- IfcSimpleValue : https://ifc43-docs.standards.buildingsmart.org/IFC/RELEASE/IFC4x3/HTML/lexical/IfcSimpleValue.htm321- IfcMeasureValue : https://ifc43-docs.standards.buildingsmart.org/IFC/RELEASE/IFC4x3/HTML/lexical/IfcMeasureValue.htm322- IfcDerivedMeasureValue : https://ifc43-docs.standards.buildingsmart.org/IFC/RELEASE/IFC4x3/HTML/lexical/IfcDerivedMeasureValue.htm323- IFC2x3 IfcSimpleValue : https://standards.buildingsmart.org/IFC/RELEASE/IFC2x3/TC1/HTML/ifcmeasureresource/lexical/ifcsimplevalue.htm324325### Related skills326327- `ifc-syntax-express` : the EXPRESS meta-language : `TYPE`, `SELECT`, `ENUMERATION`,328 `WHERE`, the base types this skill's defined types are built on.329- `ifc-syntax-units` : how a measure type's unit type resolves to a concrete unit330 via `IfcUnitAssignment`.331- `ifc-syntax-property-sets` : where `IfcValue`-typed property values are carried.