XbimEssentials icon indicating copy to clipboard operation
XbimEssentials copied to clipboard

IFC Enums should default to NOTDEFINED rather than first defined enum

Open andyward opened this issue 1 year ago • 1 comments

When we define an IFC Enum (such as IfcSlabTypeEnum) from code-gen, we define the enum values in the order they are in EXPRESS. e.g.


public enum IfcSlabTypeEnum : byte
{
	@FLOOR ,
	@ROOF ,
	@LANDING ,
	@BASESLAB ,
	@USERDEFINED ,
	@NOTDEFINED 
}

We're not specifying any integer values so the first enum will have a value of zero, and so becomes the implicit default. The net result is that any object with an enum like this will default to that first value, unless a value is set explicitly. Two examples of how this can happen:

  1. var slab = model.Instance.New<IfcSlabType>(); where slab.PredefinedType will default to FLOOR
  2. #1=IFCSLABTYPE('1hqIFTRjfV6AWq_bMtnZwI',$,$,$,$,$,$,$,$,$) where PredefinedType on the entity will also default to FLOOR, because the last parameter (PDT) is null

While both examples are technically invalid IFC, we still accept them, and will then report the type as being PredefinedType FLOOR. On different types it's obviously a different value, but still typically a value that would surprise.

Should we consider updating the codegen in a future release so any occurrence of 'NOTDEFINED' (or equivalent) will be the first in the Enum, meaning any default value would give conceptually accurate output. Obviously a breaking interface change so would need to align with a major release. Alternatively we need to initialise these Mandatory enum properties explicitly to an appropriate value.

andyward avatar Sep 05 '24 17:09 andyward

An additional issue with this behaviour is that different schemas can have a different default enum value meaning you can get a different default enum value between IFC2x3, IFC4 and IFC4x3 entities of the same type. E.g. for IFCWallTypes across schemas the default PDT is as follows:

IFC Version Default PredefinedType
IFC2x3 STANDARD
IFC4 MOVABLE
IFC4x3 ELEMENTEDWALL

.. which creates inconsistencies unless the application is explicit about setting a value.

A workaround for this is to hook into the IModel.EntityNew event handler with logic such as:


model.EntityNew += EntityAdded;

private void EntityAdded(IPersistEntity entity)
{
   if (entity is IIfcObjectDefinition obj)
   {
       obj.SetPredefinedTypeValue("NOTDEFINED"); // Silently sets any PredefinedType enumeration field to NOTDEFINED if the entity has the member and a NOTDEFINED enum exists 
   }
}

(using the new SetPredefinedTypeValue() method)

andyward avatar Apr 28 '25 13:04 andyward