IfcModelExtension#
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#
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#
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#
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) {
// 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#
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
psetNameas 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#
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) {
// 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#
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
qsetNameas 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#
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#
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#
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#
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);
}
// 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;
// linear placement (not supported)...
} else {
return result;
}
}
getBody3dGeometricContext() extension#
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#
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#
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)) {
// 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);
// infinite loop
if (id > -1) {
return [];
}
result.add(current);
}
} catch (e) {
return result;
}
return result;
}
getShapesInLayer() extension#
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);
}
