Загрузка данных
using System;
using System.Collections.Generic;
using System.Linq;
using Xbim.Ifc;
using Xbim.Ifc4.Interfaces;
using Xbim.Ifc4.Kernel;
using Xbim.Ifc4.PropertyResource;
using Xbim.Ifc4.MeasureResource;
namespace IfcBimEditor
{
public sealed class ElementItem
{
public IIfcObject Element { get; set; }
public string Display => $"{Element.ExpressType.Name} | {Element.Name} | {Element.GlobalId}";
}
public static class IfcEditor
{
public static List<IIfcObject> FindSimilar(IfcStore model, IIfcObject selected, int mode)
{
var all = model.Instances.OfType<IIfcObject>();
switch (mode)
{
case 1:
return all.Where(x => string.Equals(
x.Name.ToString(), selected.Name.ToString(),
StringComparison.OrdinalIgnoreCase)).ToList();
case 2:
var type = selected.IsTypedBy.FirstOrDefault()?.RelatingType;
return type == null
? new List<IIfcObject> { selected }
: all.Where(x => x.IsTypedBy.Any(r =>
r.RelatingType != null && r.RelatingType.GlobalId == type.GlobalId)).ToList();
default:
return all.Where(x => x.ExpressType.Name == selected.ExpressType.Name).ToList();
}
}
// Редактирует строковое свойство IFC4. Для IFC2x3 нужен отдельный обработчик.
// Не изменяет исходный общий Pset: создаёт новый для каждого выбранного объекта.
public static int SetStringProperty(IfcStore model, IEnumerable<IIfcObject> objects,
string psetName, string propertyName, string value, bool createMissing)
{
if (string.IsNullOrWhiteSpace(psetName) || string.IsNullOrWhiteSpace(propertyName))
throw new ArgumentException("Укажите имя набора свойств и свойства.");
var targets = objects.Distinct().ToList();
// Проверяем совместимость до начала транзакции.
if (targets.Any(o => !(o is IfcObjectDefinition)))
throw new NotSupportedException("Этот редактор поддерживает запись только в IFC4. Для IFC2x3 требуется отдельная реализация.");
int changed = 0;
using (var tx = model.BeginTransaction("Bulk property edit"))
{
foreach (var obj in targets)
{
var relation = obj.IsDefinedBy
.OfType<IIfcRelDefinesByProperties>()
.FirstOrDefault(r => r.RelatingPropertyDefinition is IIfcPropertySet ps &&
ps.Name.ToString() == psetName);
var set = relation?.RelatingPropertyDefinition as IIfcPropertySet;
var existing = set?.HasProperties.OfType<IIfcPropertySingleValue>()
.FirstOrDefault(p => p.Name.ToString() == propertyName);
if (existing == null && !createMissing) continue;
var newSet = model.Instances.New<IfcPropertySet>(p => p.Name = psetName);
if (set != null)
{
foreach (var oldProp in set.HasProperties)
{
if (oldProp.Name.ToString() == propertyName) continue;
// Сохраняем остальные свойства как ссылки, не изменяя их значения.
// Изменяемое свойство создаётся заново ниже.
var concrete = oldProp as IfcProperty;
if (concrete == null)
throw new NotSupportedException("Набор содержит свойства несовместимой IFC-схемы.");
newSet.HasProperties.Add(concrete);
}
}
newSet.HasProperties.Add(model.Instances.New<IfcPropertySingleValue>(p =>
{
p.Name = propertyName;
p.NominalValue = new IfcText(value ?? string.Empty);
}));
model.Instances.New<IfcRelDefinesByProperties>(r =>
{
r.RelatingPropertyDefinition = newSet;
r.RelatedObjects.Add((IfcObjectDefinition)obj);
});
if (relation != null)
{
var oldRelation = relation as IfcRelDefinesByProperties;
if (oldRelation == null)
throw new NotSupportedException("Связь Pset не относится к IFC4.");
oldRelation.RelatedObjects.Remove((IfcObjectDefinition)obj);
if (!oldRelation.RelatedObjects.Any()) model.Delete(oldRelation);
}
changed++;
}
tx.Commit();
}
return changed;
}
}
}