IfcModelExtension
PIComposer APIPIComposer API

IfcModelExtension#

extension IfcModelExtension on IIfcModel

Extension on IIfcModel providing convenient helper functions for IFC model handling. Includes functions to create commonly occurring instance types and utilities for model manipulation and querying.

Methods#

createIfcProject() extension#

IInstance createIfcProject()

Creates an IFC Project instance including all context information. Uses header data for author and organization information.

Available on IIfcModel, provided by the IfcModelExtension extension

Implementation
IInstance createIfcProject() {
  final header = getHeader();
  final fileName = header.getInstance(attName: 'filename');
  final author = fileName.getStrings(attName: 'author');
  // ifcpersion
  final person = createInstance(typeName: 'IFCPERSON');
  final familyName = author.isNotEmpty ? author.first : '';
  final givenName = author.length > 1 ? author[1] : '';
  if (familyName.isNotEmpty) {
    person.setAttribute(familyName, attName: 'FamilyName');
  }
  if (givenName.isNotEmpty) {
    person.setAttribute(givenName, attName: 'GivenName');
  }
  // IFCORGANIZATION
  final headerOrg = fileName.getStrings(attName: 'organization');
  final orgName = headerOrg.isNotEmpty ? headerOrg.first : '';
  final organization = createInstance(typeName: 'IFCORGANIZATION')
    ..setAttribute(orgName, attName: 'Name');
  // IFCAPPLICATION
  final app = createInstance(typeName: 'IFCAPPLICATION')
    ..setInstanceRef(organization, attIndex: 0)
    ..setAttribute('1.0', attIndex: 1)
    ..setAttribute('PIComposer', attIndex: 2)
    ..setAttribute('PIC', attIndex: 3);
  // IFCPERSONANDORGANIZATION
  final personorg = createInstance(typeName: 'IFCPERSONANDORGANIZATION')
    ..setInstanceRef(person, attIndex: 0)
    ..setInstanceRef(organization, attIndex: 1);
  // IFCOWNERHISTORY
  final stateEnum =
      createEnum(typeName: 'IfcStateEnum', stringValue: 'READWRITE');
  final seconds = DateTime.now().millisecondsSinceEpoch ~/ 1000;
  final ownerHist = createInstance(typeName: 'IFCOWNERHISTORY')
    ..setInstanceRef(personorg, attIndex: 0)
    ..setInstanceRef(app, attIndex: 1)
    ..setAttribute(stateEnum, attIndex: 2)
    ..setAttribute(seconds, attIndex: 7);
  // application context...
  final zero = [0.0, 0.0, 0.0];
  final ratioZ = [0.0, 0.0, 1.0];
  final ratiox = [1.0, 0.0, 0.0];
  final north = [0.0, 1.0];
  final contextaxispl3d = createAxis2Placement3D(zero, ratioZ, ratiox);
  final trueNorth = createInstance(typeName: 'IfcDirection');
  trueNorth.setAttribute(north, attName: 'DirectionRatios');
  // IFCGEOMETRICREPRESENTATIONCONTEXT
  final geomcontext =
      createInstance(typeName: 'IFCGEOMETRICREPRESENTATIONCONTEXT')
        ..setAttribute('Model', attIndex: 1)
        ..setAttribute(3, attIndex: 2)
        ..setAttribute(1.0e-5, attIndex: 3);
  final wcSel = createSelect(typeId: Axis2PlacementId)
    ..setSelectedType(typeId: contextaxispl3d.typeId)
    ..setValue(contextaxispl3d);
  geomcontext.setAttribute(wcSel, attIndex: 4);
  geomcontext.setAttribute(attName: 'TrueNorth', trueNorth);
  //IFCGEOMETRICREPRESENTATIONSUBCONTEXT
  final subcontext =
      createInstance(typeName: 'IFCGEOMETRICREPRESENTATIONSUBCONTEXT')
        ..setAttribute('Body', attIndex: 0)
        ..setAttribute('Model', attIndex: 1)
        ..setAttribute(attName: 'CoordinateSpaceDimension', 3)
        ..setInstanceRef(geomcontext, attIndex: 6);
  final subcontextFootPrint =
      createInstance(typeName: 'IFCGEOMETRICREPRESENTATIONSUBCONTEXT')
        ..setAttribute('FootPrint', attIndex: 0)
        ..setAttribute('Model', attIndex: 1)
        ..setAttribute(attName: 'CoordinateSpaceDimension', 2)
        ..setInstanceRef(geomcontext, attIndex: 6);
  final subcontextAxis =
      createInstance(typeName: 'IFCGEOMETRICREPRESENTATIONSUBCONTEXT')
        ..setAttribute('Axis', attIndex: 0)
        ..setAttribute('Model', attIndex: 1)
        ..setAttribute(attName: 'CoordinateSpaceDimension', 1)
        ..setInstanceRef(geomcontext, attIndex: 6);
  // TargetView
  final targetView = createEnum(
      typeName: 'IfcGeometricProjectionEnum', stringValue: 'MODEL_VIEW');
  subcontext.setAttribute(targetView, attIndex: 8);
  subcontextFootPrint.setAttribute(targetView, attIndex: 8);
  subcontextAxis.setAttribute(targetView, attIndex: 8);
  final unitAssign = createModelUnits();
  //IFCPROJECT
  final projName = fileName.getString(attIndex: 0).getOrElse(() => '');
  final proj = createInstance(typeId: ProjectId)
    ..setAttribute(PIComposerAPIFFI.getGuid(), attIndex: 0)
    ..setInstanceRef(ownerHist, attIndex: 1, addInverse: false)
    ..setAttribute(projName, attIndex: 2)
    ..addInstanceRef(geomcontext, attIndex: 7, addInverse: false)
    ..setInstanceRef(unitAssign, attIndex: 8, addInverse: false);
  saveInstances([
    person,
    organization,
    personorg,
    ownerHist,
    app,
    geomcontext,
    subcontext,
    subcontextAxis,
    subcontextFootPrint,
    unitAssign,
    proj,
  ]);
  return proj;
}

createModelUnits() extension#

IInstance createModelUnits()

Creates default IFCUNITASSIGNMENT for PIComposer IFC model. Length measure is in millimeters, other measures follow metric MKS system.

Available on IIfcModel, provided by the IfcModelExtension extension

Implementation
IInstance createModelUnits() {
  final unitAssignSelects = <ISelect>[];
  unitAssignSelects.add(_createLengthUnit());
  unitAssignSelects.add(_createAngleUnit());
  unitAssignSelects.add(_createAreaUnit());
  unitAssignSelects.add(_createVolumeUnit());
  unitAssignSelects.add(_createMassUnit());
  unitAssignSelects.add(_createTimeUnit());
  unitAssignSelects.add(_createSolidAngleUnit());
  unitAssignSelects.add(_createTemperatureUnit());
  unitAssignSelects.add(_createLumenUnit());
  return createInstance(typeName: 'IFCUNITASSIGNMENT')
    ..setAttribute(unitAssignSelects, attIndex: 0);
}

createPSetFromTemplate() extension#

IInstance createPSetFromTemplate(IBlocklyTemplate psetTemplate)

Creates an IfcPropertySet from an IBlocklyPropertySetTemplate.

psetTemplate provides the property set definition template. Returns a null instance if parsing fails or template is invalid.

Available on IIfcModel, provided by the IfcModelExtension extension

Implementation
IInstance createPSetFromTemplate(
  IBlocklyTemplate psetTemplate,
) {
  if (psetTemplate is! IBlocklyPropertySetTemplate) {
    return createNullInstance();
  }
  final dictionary = psetTemplate.getDictionary();
  final parser = PSetTemplateParser(dictionary, PSetTemplate());
  if (!parser.parse()) {
    return createNullInstance();
  }
  PSetTemplate template = parser.template;
  final pset = createInstance(typeId: PropertySetId)
    ..setAttribute(PIComposerAPIFFI.getGuid(), attIndex: 0)
    ..setAttribute(template.type, attIndex: 2);
  final ps = <IInstance>[];
  for (final p in template.properties) {
    try {
      final prop = _createProperty(p);
      ps.add(prop);
    } catch (e) {
      &#47;&#47; Skip property on error
    }
  }
  pset.setAttribute(ps, attIndex: 4);
  final ifcPropertySetDefinitionSelect =
      createSelect(typeName: 'IfcPropertySetDefinitionSelect')
        ..setSelectedType(typeName: 'IfcPropertySet')
        ..setValue(pset);
  final relDef = createInstance(typeId: RelDefinesByPropertiesId)
    ..setAttribute(PIComposerAPIFFI.getGuid(), attIndex: 0)
    ..setAttribute(ifcPropertySetDefinitionSelect, attIndex: 5);
  return relDef;
}

createPSetOfType() extension#

IInstance createPSetOfType(String psetName)

Creates a predefined IfcPropertySet with the given type name.

This method creates a standard IFC property set structure including:

  • An IfcPropertySet instance with a generated GUID
  • The specified psetName as the property set type identifier
  • A relational structure (IfcRelDefinesByProperties) that links the property set to potential elements

psetName should be a valid IFC property set type name (e.g., 'Pset_WallCommon', 'Pset_BeamCommon') either defined in the schema EXPRESS file or is defined via a template.

Returns an IInstance of IfcRelDefinesByProperties that can be associated with building elements to assign the property set.

Example:

final relPset = createPSetOfType('Pset_WallCommon');
final wall = createInstance(typeName: 'IfcWall');
relPset.addInstanceRef(wall, attName: 'RelatedObjects');

Available on IIfcModel, provided by the IfcModelExtension extension

Implementation
IInstance createPSetOfType(String psetName) {
  final pset = createInstance(typeId: PropertySetId)
    ..setAttribute(PIComposerAPIFFI.getGuid(), attIndex: 0)
    ..setAttribute(psetName, attIndex: 2);
  final ifcPropertySetDefinitionSelect =
      createSelect(typeName: 'IfcPropertySetDefinitionSelect')
        ..setSelectedType(typeName: 'IfcPropertySet')
        ..setValue(pset);
  final relDef = createInstance(typeId: RelDefinesByPropertiesId)
    ..setAttribute(PIComposerAPIFFI.getGuid(), attIndex: 0)
    ..setAttribute(ifcPropertySetDefinitionSelect,
        attName: 'RelatingPropertyDefinition');
  return relDef;
}

createQSetFromTemplate() extension#

IInstance createQSetFromTemplate(IBlocklyTemplate qsetTemplate)

Creates an IfcQuantitySet from an IBlocklyQuantitySetTemplate.

qsetTemplate provides the quantity set definition template. Returns a null instance if parsing fails or template is invalid.

Available on IIfcModel, provided by the IfcModelExtension extension

Implementation
IInstance createQSetFromTemplate(
  IBlocklyTemplate qsetTemplate,
) {
  if (qsetTemplate is! IBlocklyQuantitySetTemplate) {
    return createNullInstance();
  }
  final dictionary = qsetTemplate.getDictionary();
  if (dictionary.isEmpty) {
    return createNullInstance();
  }
  final parser = QuantitySetParser(dictionary, QuantitySetTemplate());
  if (!parser.parse()) {
    return createNullInstance();
  }
  final template = parser.template;
  final qset = createInstance(typeId: ElementQuantityId);
  qset.setAttribute(PIComposerAPIFFI.getGuid(), attIndex: 0);
  qset.setAttribute(template.type, attIndex: 2);
  final qs = <IInstance>[];
  for (final q in template.quantitys) {
    try {
      final quant = _createQuantity(q);
      qs.add(quant);
    } catch (e) {
      &#47;&#47; Skip quantity on error
    }
  }
  qset.setAttribute(attName: 'Quantities', qs);
  final ifcPropertySetDefinitionSelect =
      createSelect(typeName: 'IfcPropertySetDefinitionSelect')
        ..setSelectedType(typeName: 'IfcPropertySet')
        ..setValue(qset);
  final relDef = createInstance(typeId: RelDefinesByPropertiesId)
    ..setAttribute(PIComposerAPIFFI.getGuid(), attIndex: 0)
    ..setAttribute(ifcPropertySetDefinitionSelect, attIndex: 5);
  return relDef;
}

createQSetOfType() extension#

IInstance createQSetOfType(String qsetName)

Creates a predefined IfcQuantitySet with the given type name.

This method creates a standard IFC quantity set structure including:

  • An IfcElementQuantity instance with a generated GUID
  • The specified qsetName as the quantity set type identifier
  • A relational structure (IfcRelDefinesByProperties) that links the quantity set to potential elements

qsetName should be a valid IFC quantity set type name (e.g., 'Qto_WallBaseQuantities', 'Qto_BeamBaseQuantities').

Returns an IInstance of IfcRelDefinesByProperties that can be associated with building elements to assign the quantity set.

Example:

final relPset = createQSetOfType('Qto_WallBaseQuantities');
final wall = createInstance(typeName: 'IfcWall');
relPset.addInstanceRef(wall, attName: 'RelatedObjects');

Available on IIfcModel, provided by the IfcModelExtension extension

Implementation
IInstance createQSetOfType(String qsetName) {
  final pset = createInstance(typeId: ElementQuantityId)
    ..setAttribute(PIComposerAPIFFI.getGuid(), attIndex: 0)
    ..setAttribute(qsetName, attIndex: 2);
  final ifcPropertySetDefinitionSelect =
      createSelect(typeName: 'IfcPropertySetDefinitionSelect')
        ..setSelectedType(typeName: 'IfcPropertySet')
        ..setValue(pset);
  final relDef = createInstance(typeId: RelDefinesByPropertiesId)
    ..setAttribute(PIComposerAPIFFI.getGuid(), attIndex: 0)
    ..setAttribute(ifcPropertySetDefinitionSelect,
        attName: 'RelatingPropertyDefinition');
  return relDef;
}

createRelAggregate() extension#

IInstance createRelAggregate({ IInstance? parent, IInstance? child})

Creates an IfcRelAggregates relationship.

Optional parent and child parameters set the relationship endpoints.

Available on IIfcModel, provided by the IfcModelExtension extension

Implementation
IInstance createRelAggregate({IInstance? parent, IInstance? child}) {
  final relAg = createInstance(typeId: RelAggregatesId)
    ..setAttribute(PIComposerAPIFFI.getGuid(), attIndex: 0);
  if (null != parent) {
    relAg.setInstanceRef(parent, attIndex: 4);
  }
  if (null != child) {
    relAg.addInstanceRef(child, attIndex: 5, addInverse: false);
  }
  return relAg;
}

createRelContainSpatial() extension#

IInstance createRelContainSpatial({ IInstance? parent, IInstance? child})

Creates an IfcRelContainedInSpatialStructure relationship.

Optional parent and child parameters set the relationship endpoints.

Available on IIfcModel, provided by the IfcModelExtension extension

Implementation
IInstance createRelContainSpatial({IInstance? parent, IInstance? child}) {
  final relContain = createInstance(typeId: RelContainedInSpatialStructureId)
    ..setAttribute(PIComposerAPIFFI.getGuid(), attIndex: 0);
  if (null != parent) {
    relContain.setInstanceRef(parent, attIndex: 5);
  }
  if (null != child) {
    relContain.addInstanceRef(child, attIndex: 4, addInverse: false);
  }
  return relContain;
}

createStyledItem() extension#

IInstance createStyledItem(List<double> color)

Creates an IfcStyledItem from RGBA color values.

color must contain at least 3 values (RGBA), A default to 0.0. Returns a null instance if color data is insufficient.

Available on IIfcModel, provided by the IfcModelExtension extension

Implementation
IInstance createStyledItem(List<double> color) {
  if (color.length < 3) {
    return createNullInstance();
  }
  final ifcColourRgb = createInstance(typeName: 'IFCCOLOURRGB')
    ..setAttribute(color[0], attIndex: 1)
    ..setAttribute(color[1], attIndex: 2)
    ..setAttribute(color[2], attIndex: 3);

  final reflectance = createEnum(
      typeName: 'IfcReflectanceMethodEnum', stringValue: 'NOTDEFINED');
  final ifcSurfaceStyleRendering =
      createInstance(typeName: 'IFCSURFACESTYLERENDERING')
        ..setAttribute(ifcColourRgb, attName: 'SurfaceColour')
        ..setAttribute(color.length == 4 ? color[3] : 0.0,
            attName: 'Transparency')
        ..setAttribute(reflectance, attName: 'ReflectanceMethod');

  final surfaceStyleElementSelect =
      createSelect(typeName: 'IFCSURFACESTYLEELEMENTSELECT')
        ..setSelectedType(typeId: ifcSurfaceStyleRendering.typeId)
        ..setValue(ifcSurfaceStyleRendering);

  final ifcSurfaceSideEnum =
      createEnum(typeName: 'IfcSurfaceSide', stringValue: 'POSITIVE');
  final styles = [surfaceStyleElementSelect];

  final ifcSurfaceStyle = createInstance(typeName: 'IFCSURFACESTYLE')
    ..setAttribute(ifcSurfaceSideEnum, attName: 'Side')
    ..setAttribute(styles, attName: 'Styles');
  final surfaceStyles = [ifcSurfaceStyle];
  return createInstance(typeName: 'IFCSTYLEDITEM')
    ..setAttribute(surfaceStyles, attName: 'Styles');
}

getAbsolutePlacement() extension#

Matrix4 getAbsolutePlacement(IInstance instance)

Gets the absolute transformation matrix for an IfcProduct instance.

Supports local placements and grid placements with polyline grids. Returns identity matrix for unsupported placement types.

Available on IIfcModel, provided by the IfcModelExtension extension

Implementation
Matrix4 getAbsolutePlacement(IInstance instance) {
  var result = Matrix4.identity();
  final placement = getInstancePlacement(instance);
  if (placement.isNull) {
    return result;
  }
  List<IInstance> placements = <IInstance>[];
  final typeId = placement.typeId;
  if (typeId == GridPlacementId) {
    final relativeTo =
        placement.getInstance(attName: 'PlacementRelTo', resolveRef: true);
    if (relativeTo.isNull || relativeTo.typeId != LocalPlacementId) {
      return result;
    }
    placements = getPlacementHierarchy(relativeTo);
    final reverse = placements.reversed;
    for (final p in reverse) {
      final m = placementToMatrix(p);
      if (m.isIdentity()) {
        continue;
      }
      result.multiply(m);
    }
    &#47;&#47; get grid axes intersections..
    final pLocation =
        placement.getInstance(attName: 'PlacementLocation', resolveRef: true);
    if (pLocation.isNull) {
      return result;
    }
    final location = getVirtualGridIntersection(pLocation);
    if (!isZero(location)) {
      final translate =
          Matrix4.translation(Vector3(location.x, location.y, location.z));
      translate.multiply(result);
      return translate;
    }
    return result;
  } else if (typeId == LocalPlacementId) {
    placements = getPlacementHierarchy(placement);
    final reverse = placements.reversed;
    for (final p in reverse) {
      final m = placementToMatrix(p);
      if (m.isIdentity()) {
        continue;
      }
      result.multiply(m);
    }
    return result;
    &#47;&#47; linear placement (not supported)...
  } else {
    return result;
  }
}

getBody3dGeometricContext() extension#

IInstance getBody3dGeometricContext()

Gets the 3D geometric representation context for body shapes. Prefers subcontexts with 'Body' identifier, falls back to model context.

Available on IIfcModel, provided by the IfcModelExtension extension

Implementation
IInstance getBody3dGeometricContext() {
  final contexts =
      getInstancesByType(typeId: GeometricRepresentationSubContextId);
  IInstance candidate = createNullInstance();
  for (final context in contexts) {
    final type =
        context.getString(attName: 'ContextType').getOrElse(() => '');
    if (type.isEmpty) {
      continue;
    }
    final identifier =
        context.getString(attName: 'ContextIdentifier').getOrElse(() => '');
    if (identifier.isEmpty) {
      continue;
    }
    final dim = context
        .getInt(attName: 'CoordinateSpaceDimension')
        .getOrElse(() => 0);
    final view = context.getEnum(attName: 'TargetView');
    if ((view.stringValue.toUpperCase() == 'MODEL_VIEW') &&
        (type.toLowerCase() == 'model') &&
        (identifier.toLowerCase() == 'body') &&
        (dim == 3)) {
      return context;
    } else if ((view.stringValue.toUpperCase() == 'MODEL_VIEW') &&
        (type.toLowerCase() == 'model') &&
        (identifier.toLowerCase() == 'body')) {
      candidate = context;
    }
  }
  return candidate;
}

getInstancePlacement() extension#

IInstance getInstancePlacement(IInstance inst)

Gets the object placement instance for an IfcProduct.

Available on IIfcModel, provided by the IfcModelExtension extension

Implementation
IInstance getInstancePlacement(IInstance inst) {
  final placement = inst.getInstance(attName: 'ObjectPlacement');
  if (placement.isNull || !placement.isInstanceReference) {
    return placement;
  }
  final handle = placement.instanceHandle;
  return getInstance(handle);
}

getPlacementHierarchy() extension#

List<IInstance> getPlacementHierarchy(IInstance instance)

Gets the relative placement hierarchy for a local placement instance.

instance must be an IfcLocalPlacement. Returns empty list for invalid placements or infinite loops.

Available on IIfcModel, provided by the IfcModelExtension extension

Implementation
List<IInstance> getPlacementHierarchy(IInstance instance) {
  final result = <IInstance>[];
  if (instance.typeId != LocalPlacementId) {
    return result;
  }
  try {
    IInstance current = instance;
    result.add(current);
    while (!current.isNullAttribute(attIndex: 0).getOrElse(() => true)) {
      &#47;&#47; get relativeTo ref...
      final relatedTo = current.getInstance(attIndex: 0);
      if (relatedTo.referencedTypeId != LocalPlacementId) {
        return [];
      }
      current = getInstance(relatedTo.instanceHandle);
      final id =
          result.indexWhere((inst) => inst.instanceId == current.instanceId);
      &#47;&#47; infinite loop
      if (id > -1) {
        return [];
      }
      result.add(current);
    }
  } catch (e) {
    return result;
  }
  return result;
}

getShapesInLayer() extension#

List<IInstance> getShapesInLayer(IInstance layer)

Gets all shape representations in a specific layer.

Available on IIfcModel, provided by the IfcModelExtension extension

Implementation
List<IInstance> getShapesInLayer(IInstance layer) {
  final handles = <InstanceHandle>[];
  if (layer.isNull) {
    return [];
  }
  final shapeSels = layer.getSelects(attName: 'AssignedItems');
  for (final sel in shapeSels) {
    final shape = sel.getInstance();
    handles.add(shape.instanceHandle);
  }
  return getInstancesByHandle(handles);
}