第09章:属性集、量集、材料与分类系统
IFC 模型最有价值的不是几何,而是挂在几何之上的语义信息:属性集(Pset)、量集(Qto)、材料(Material)、分类(Classification)。本章系统讲解这些信息的数据结构以及在 Xbim 中的读写方式。
1. 属性集(Property Set)
1.1 IFC 数据结构
IfcRoot ──IfcRelDefinesByProperties──> IfcPropertySet
├── IfcPropertySingleValue
├── IfcPropertyEnumeratedValue
├── IfcPropertyTableValue
├── IfcPropertyListValue
├── IfcPropertyBoundedValue
└── IfcPropertyReferenceValue
IfcPropertySet 表达”一组键值对的集合”,最常见的是 IfcPropertySingleValue(单值)。属性的”类型 + 单位”信息通过 IfcValue(如 IfcLengthMeasure、IfcText、IfcBoolean)显式携带。
1.2 标准 PSet 命名规则
buildingSMART 维护一份 Pset Definitions, 命名规则:
Pset_<Object>Common:通用属性(如Pset_WallCommon、Pset_DoorCommon);Pset_<Object><Aspect>:特定方面(如Pset_WallCladding);- 自定义集应避免
Pset_前缀,使用项目代号(如Acme_Custom)。
1.3 在 Xbim 中读取
最简单的方式:用 Xbim.Ifc.Extensions 的扩展方法。
using Xbim.Ifc.Extensions;
bool? isExternal = wall.GetPropertySingleValue<IfcBoolean>("Pset_WallCommon", "IsExternal");
double? rating = wall.GetPropertySingleValue<IfcReal>("Pset_WallCommon", "FireRating");
底层会查 IsDefinedBy → IfcRelDefinesByProperties → IfcPropertySet[Name] → HasProperties[Name]。
通用迭代:
foreach (var rel in wall.IsDefinedBy.OfType<IIfcRelDefinesByProperties>())
{
if (rel.RelatingPropertyDefinition is IIfcPropertySet pset)
{
Console.WriteLine($"== {pset.Name} ==");
foreach (var p in pset.HasProperties.OfType<IIfcPropertySingleValue>())
Console.WriteLine($" {p.Name} = {p.NominalValue?.Value} ({p.NominalValue?.GetType().Name})");
}
}
1.4 在 Xbim 中写入
using var txn = model.BeginTransaction("Set Pset");
wall.SetPropertySingleValue("Pset_WallCommon", "IsExternal", true);
wall.SetPropertySingleValue("Pset_WallCommon", "FireRating", "REI60");
wall.SetPropertySingleValue("Pset_WallCommon", "ThermalTransmittance",
new IfcThermalTransmittanceMeasure(0.27));
txn.Commit();
SetPropertySingleValue 的智能行为:
- 没有该 PSet 时自动创建
IfcPropertySet; - 没有该属性时新增
IfcPropertySingleValue; - 已有但值不同时更新;
- 没有
IfcRelDefinesByProperties时自动建立。
1.5 类型属性 vs 实例属性
挂在 IfcWallType 上的 PSet 适用于该类型的所有实例(”该型号的墙都防火 60 分钟”),挂在 IfcWall 实例上的属性则覆盖类型默认值。读取时建议先看实例,再回退到类型:
public static T? GetEffective<T>(IIfcObject o, string pset, string name)
where T : IIfcValue
{
var v = o.GetPropertySingleValue<T>(pset, name);
if (v != null) return v;
var type = o.IsTypedBy.FirstOrDefault()?.RelatingType;
return type?.GetPropertySingleValue<T>(pset, name);
}
2. 量集(Quantity Set)
2.1 数据结构
IfcRoot ──IfcRelDefinesByProperties──> IfcElementQuantity
├── IfcQuantityLength
├── IfcQuantityArea
├── IfcQuantityVolume
├── IfcQuantityCount
├── IfcQuantityWeight
└── IfcQuantityTime
注意:IfcElementQuantity 是 IfcPropertySetDefinition 的子类,它和 IfcPropertySet 共用同一种关系实体 IfcRelDefinesByProperties。
标准量集名以 Qto_ 开头,例如 Qto_WallBaseQuantities、Qto_SlabBaseQuantities、Qto_SpaceBaseQuantities。
2.2 读取
double area = wall.GetQuantitySetValue<double>("Qto_WallBaseQuantities", "NetSideArea");
double vol = wall.GetQuantitySetValue<double>("Qto_WallBaseQuantities", "NetVolume");
int cnt = space.GetQuantitySetValue<int>("Qto_SpaceBaseQuantities", "PerimeterAcousticRating");
通用:
foreach (var rel in wall.IsDefinedBy.OfType<IIfcRelDefinesByProperties>())
{
if (rel.RelatingPropertyDefinition is IIfcElementQuantity qto)
{
Console.WriteLine($"== {qto.Name} ==");
foreach (var q in qto.Quantities)
{
switch (q)
{
case IIfcQuantityLength l: Console.WriteLine($"{l.Name} = {l.LengthValue} mm"); break;
case IIfcQuantityArea a: Console.WriteLine($"{a.Name} = {a.AreaValue} mm²"); break;
case IIfcQuantityVolume v: Console.WriteLine($"{v.Name} = {v.VolumeValue} mm³"); break;
case IIfcQuantityCount c: Console.WriteLine($"{c.Name} = {c.CountValue}"); break;
}
}
}
}
2.3 写入
using var txn = model.BeginTransaction("Set Qto");
wall.SetElementPhysicalSimpleQuantity<IfcQuantityLength>("Qto_WallBaseQuantities", "Length",
new IfcLengthMeasure(5000));
wall.SetElementPhysicalSimpleQuantity<IfcQuantityVolume>("Qto_WallBaseQuantities", "NetVolume",
new IfcVolumeMeasure(2.5));
txn.Commit();
注意:量集的值必须用对应单位类型(
IfcLengthMeasure、IfcAreaMeasure、IfcVolumeMeasure、IfcCountMeasure)包装。
3. 材料系统
材料体系比属性集复杂,因为同一构件可能由”多层 + 多种材质”组成(例如外墙的”内饰面–保温层–结构层–外饰面”)。
3.1 主要类型
| 实体 | 含义 |
|---|---|
IfcMaterial |
单一材料(例如”C30 混凝土”、”100mm 岩棉”) |
IfcMaterialList |
多个材料的简单清单(IFC2x3 时代的简化方案) |
IfcMaterialLayerSet |
有顺序的多层材料(墙、板典型用法) |
IfcMaterialLayer |
单层(含厚度、IsVentilated、Priority) |
IfcMaterialLayerSetUsage |
LayerSet 在构件中的”位置”与”方向”(按厚度从内到外) |
IfcMaterialProfileSet / IfcMaterialProfile |
用于梁、柱(沿截面轮廓分配材料) |
IfcMaterialConstituentSet |
IFC4 通用材料组合(更灵活) |
3.2 读取墙的多层结构
foreach (var assoc in wall.HasAssociations.OfType<IIfcRelAssociatesMaterial>())
{
var mat = assoc.RelatingMaterial;
switch (mat)
{
case IIfcMaterial m:
Console.WriteLine($"single: {m.Name}");
break;
case IIfcMaterialLayerSet ls:
foreach (var layer in ls.MaterialLayers)
Console.WriteLine($"layer: {layer.Material?.Name}, t={layer.LayerThickness}");
break;
case IIfcMaterialLayerSetUsage lsu:
Console.WriteLine($"usage: dir={lsu.LayerSetDirection}, sense={lsu.DirectionSense}");
foreach (var layer in lsu.ForLayerSet.MaterialLayers)
Console.WriteLine($"layer: {layer.Material?.Name}, t={layer.LayerThickness}");
break;
}
}
3.3 写入材料
using var txn = model.BeginTransaction("Material");
var concrete = model.Instances.New<IfcMaterial>(m => m.Name = "C30 Concrete");
var insul = model.Instances.New<IfcMaterial>(m => m.Name = "Rockwool 100");
var layerSet = model.Instances.New<IfcMaterialLayerSet>(ls =>
{
ls.MaterialLayers.Add(model.Instances.New<IfcMaterialLayer>(l => { l.Material = concrete; l.LayerThickness = 200; }));
ls.MaterialLayers.Add(model.Instances.New<IfcMaterialLayer>(l => { l.Material = insul; l.LayerThickness = 100; }));
});
var usage = model.Instances.New<IfcMaterialLayerSetUsage>(u =>
{
u.ForLayerSet = layerSet;
u.LayerSetDirection = IfcLayerSetDirectionEnum.AXIS2;
u.DirectionSense = IfcDirectionSenseEnum.POSITIVE;
u.OffsetFromReferenceLine = 0;
});
var rel = model.Instances.New<IfcRelAssociatesMaterial>(r =>
{
r.RelatingMaterial = usage;
r.RelatedObjects.Add(wall);
});
txn.Commit();
4. 分类系统
IFC 用 IfcClassification + IfcClassificationReference + IfcRelAssociatesClassification 表达分类关系。常见分类标准:
- Uniclass 2015(英国)
- OmniClass(北美)
- Masterformat / Uniformat II
- 国标 GB/T 51269(中国)
- CCS / DIN 276(欧洲)
4.1 数据结构
IfcClassification (Source, Edition, Name)
↑
│
IfcClassificationReference (Identification, Name, ReferencedSource)
↑
│
IfcRelAssociatesClassification (RelatingClassification, RelatedObjects[])
4.2 写入
using var txn = model.BeginTransaction("Classification");
var classification = model.Instances.New<IfcClassification>(c =>
{
c.Name = "Uniclass 2015";
c.Source = "RIBA Enterprises";
c.Edition = "2015";
});
var refer = model.Instances.New<IfcClassificationReference>(r =>
{
r.ReferencedSource = classification;
r.Identification = "EF_25_10";
r.Name = "External walls";
});
model.Instances.New<IfcRelAssociatesClassification>(rel =>
{
rel.RelatingClassification = refer;
rel.RelatedObjects.AddRange(model.Instances.OfType<IIfcWall>().Where(w => w.IsExternal() == true));
});
txn.Commit();
4.3 读取
foreach (var rel in wall.HasAssociations.OfType<IIfcRelAssociatesClassification>())
{
if (rel.RelatingClassification is IIfcClassificationReference r)
Console.WriteLine($"{r.ReferencedSource?.Name} : {r.Identification} - {r.Name}");
}
5. 标识码 / 编号字段
除了上述结构化系统,IFC 还有一些”扁平”字段常被用于编号:
IfcRoot.GlobalId— 唯一 GUID;IfcRoot.Name— 用户可见名称(避免依赖此字段做唯一标识);IfcObject.Tag— IFC4 之后用于”内部 ID”(很多软件用来存原生构件 ID);IfcRelAssignsToControl.RelatingControl— 编码、合同等。
6. 单位换算
属性/量集的数值都按模型默认单位(一般 mm、mm²、mm³、Hz、Pa)。如果要展示给用户,记得用 IModel.ModelFactors.LengthToMetresConversionFactor 把毫米换算为米:
double meterLen = mmLen * model.ModelFactors.LengthToMetresConversionFactor;
7. 常见反模式
- 把所有自定义属性塞进一个名为
Custom的 PSet → 应当按”作用域 + 含义”切成多个 PSet; - 用
Pset_前缀创建私有 PSet → 与 buildingSMART 标准冲突,会被 IDS 校验报错; - 直接给
wall.Name写中文长描述 → 应该用Description或 PSet; - 用
IfcMaterial.Name字符串拼接成”墙体: 200mm 砖” → 应当用 LayerSet 拆解。
8. 实战:导出”构件 + 属性 + 量”为 Excel/CSV
using var sw = new StreamWriter("walls.csv");
sw.WriteLine("GlobalId,Name,Length,Volume,IsExternal,FireRating");
foreach (var w in model.Instances.OfType<IIfcWall>())
{
var len = w.GetQuantitySetValue<double>("Qto_WallBaseQuantities", "Length");
var vol = w.GetQuantitySetValue<double>("Qto_WallBaseQuantities", "NetVolume");
var ext = w.IsExternal();
var fire = w.GetPropertySingleValue<IfcLabel>("Pset_WallCommon", "FireRating");
sw.WriteLine($"{w.GlobalId},{w.Name},{len},{vol},{ext},{fire}");
}
把这种小工具串起来,就是一个轻量”IFC → BIM 报表”流水线。Xbim 还提供 Xbim.IO.TableStore 模块可以以可配置的方式生成 Excel。
9. 小结
- 属性集承载布尔/数值/字符串等离散信息;
- 量集承载几何派生的数值;
- 材料用 LayerSet/ProfileSet/ConstituentSet 表达多层构造;
- 分类通过
IfcClassification + IfcClassificationReference关联标准; - 这些都通过
IfcRelXxx关系实体挂到对象上,Xbim 的扩展方法极大简化了访问。
下一章我们将深入”关系网络”本身:空间结构、构件的连接、洞口、装饰、群组等组织方式。