using System.Collections.Generic;
using System.Linq;
using Xbim.Ifc;
using Xbim.Ifc4.Interfaces;
namespace IfcBimEditor
{
public static class IfcSpatialTreeBuilder
{
public static List<IfcSpatialNode> Build(IfcStore model)
{
var seen = new HashSet<string>();
return model.Instances.OfType<IIfcProject>()
.Select(p => BuildNode(p, seen)).ToList();
}
private static IfcSpatialNode BuildNode(
IIfcObjectDefinition obj, HashSet<string> seen)
{
var node = new IfcSpatialNode
{
Entity = obj,
Type = obj.ExpressType.Name,
Name = obj.Name.ToString(),
Description = obj.Description.ToString()
};
if (!seen.Add(obj.GlobalId.ToString())) return node;
// IFC decomposition: project/site/building/storey/assemblies.
foreach (var rel in obj.IsDecomposedBy.OfType<IIfcRelAggregates>())
foreach (var child in rel.RelatedObjects)
if (!seen.Contains(child.GlobalId.ToString()))
node.Children.Add(BuildNode(child, seen));
// IFC spatial containment: elements assigned to a storey or space.
if (obj is IIfcSpatialStructureElement spatial)
foreach (var rel in spatial.ContainsElements)
foreach (var element in rel.RelatedElements)
if (!seen.Contains(element.GlobalId.ToString()))
node.Children.Add(BuildNode(element, seen));
return node;
}
}
}