Загрузка данных
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using Microsoft.Win32;
using Xbim.Ifc;
using Xbim.Ifc4.Interfaces;
namespace IfcBimEditor
{
public partial class MainWindow : Window
{
private IfcStore _model;
private string _openedPath;
private List<IIfcObject> _selected = new List<IIfcObject>();
private Dictionary<string, IfcTreeNode> _nodes = new Dictionary<string, IfcTreeNode>();
public MainWindow() { InitializeComponent(); }
private List<IIfcObject> Selected => _selected;
private void Open_Click(object sender, RoutedEventArgs e)
{
var dialog = new OpenFileDialog { Filter = "IFC (*.ifc)|*.ifc" };
if (dialog.ShowDialog() != true) return;
try
{
Viewer.Model = null;
_model?.Dispose();
_model = IfcStore.Open(dialog.FileName);
_openedPath = dialog.FileName;
// Создание геометрии для отображения.
var context = new Xbim.ModelGeometry.Scene.Xbim3DModelContext(_model);
context.CreateContext();
Viewer.Model = _model;
Viewer.ReloadModel();
BuildIfcTree();
StatusText.Text = $"Открыт: {_openedPath}";
}
catch (Exception ex) { MessageBox.Show(ex.Message, "Ошибка открытия"); }
}
private void BuildIfcTree()
{
_selected.Clear();
_nodes.Clear();
var objects = _model.Instances.OfType<IIfcObject>().ToList();
var groups = objects.GroupBy(o => o.ExpressType.Name)
.OrderBy(g => g.Key)
.Select(g => new IfcTreeNode
{
Type = g.Key + " (" + g.Count() + ")",
Children = new System.Collections.ObjectModel.ObservableCollection<IfcTreeNode>(
g.OrderBy(o => o.Name.ToString()).Select(o =>
{
var node = new IfcTreeNode
{
Type = o.ExpressType.Name,
Name = o.Name.ToString(),
Description = o.Description.ToString(),
Element = o
};
_nodes[o.GlobalId.ToString()] = node;
return node;
}))
}).ToList();
IfcTree.ItemsSource = groups;
UpdateProperties();
}
private void IfcTree_SelectedItemChanged(object sender,
RoutedPropertyChangedEventArgs<object> e)
{
var node = e.NewValue as IfcTreeNode;
if (node?.Element == null) return;
_selected = new List<IIfcObject> { node.Element };
UpdateProperties();
}
private void UpdateProperties()
{
var selected = Selected;
SelectedCount.Text = $"Выбрано: {selected.Count}";
var item = selected.FirstOrDefault();
if (item == null) { PropertiesGrid.ItemsSource = null; return; }
var rows = new List<PropertyRow>
{
new PropertyRow { Group = "IFC", Name = "Class", Value = item.ExpressType.Name },
new PropertyRow { Group = "IFC", Name = "GlobalId", Value = item.GlobalId.ToString() },
new PropertyRow { Group = "IFC", Name = "Name", Value = item.Name.ToString() },
new PropertyRow { Group = "IFC", Name = "Description", Value = item.Description.ToString() }
};
foreach (var rel in item.IsDefinedBy.OfType<IIfcRelDefinesByProperties>())
if (rel.RelatingPropertyDefinition is IIfcPropertySet ps)
foreach (var prop in ps.HasProperties.OfType<IIfcPropertySingleValue>())
rows.Add(new PropertyRow { Group = ps.Name.ToString(),
Name = prop.Name.ToString(), Value = prop.NominalValue?.ToString() });
PropertiesGrid.ItemsSource = rows;
}
private void Similar_Click(object sender, RoutedEventArgs e)
{
if (_model == null || Selected.Count == 0) return;
_selected = IfcEditor.FindSimilar(_model, Selected[0], MatchMode.SelectedIndex);
UpdateProperties();
StatusText.Text = $"Найдено подобных элементов: {_selected.Count}. Группа готова к редактированию.";
}
private void Apply_Click(object sender, RoutedEventArgs e)
{
if (_model == null || Selected.Count == 0) { MessageBox.Show("Выберите элементы."); return; }
var pset = PsetInput.Text.Trim();
var prop = PropertyInput.Text.Trim();
if (pset.Length == 0 || prop.Length == 0) { MessageBox.Show("Укажите Pset и имя свойства."); return; }
if (MessageBox.Show($"Изменить {prop} у {Selected.Count} элементов?",
"Подтверждение", MessageBoxButton.YesNo) != MessageBoxResult.Yes) return;
try
{
var count = IfcEditor.SetStringProperty(_model, Selected, pset, prop,
ValueInput.Text, CreateMissing.IsChecked == true);
StatusText.Text = $"Изменено элементов: {count}. Сохраните IFC.";
UpdateProperties();
}
catch (Exception ex) { MessageBox.Show(ex.Message, "Ошибка изменения"); }
}
private void Save_Click(object sender, RoutedEventArgs e)
{
if (_model == null) return;
var dialog = new SaveFileDialog { Filter = "IFC (*.ifc)|*.ifc",
FileName = System.IO.Path.GetFileNameWithoutExtension(_openedPath) + "_edited.ifc" };
if (dialog.ShowDialog() != true) return;
if (string.Equals(dialog.FileName, _openedPath, StringComparison.OrdinalIgnoreCase))
{ MessageBox.Show("Выберите новое имя файла для сохранения."); return; }
try { _model.SaveAs(dialog.FileName); StatusText.Text = "Сохранено: " + dialog.FileName; }
catch (Exception ex) { MessageBox.Show(ex.Message, "Ошибка сохранения"); }
}
protected override void OnClosed(EventArgs e) { _model?.Dispose(); base.OnClosed(e); }
public sealed class PropertyRow { public string Group { get; set; } public string Name { get; set; } public string Value { get; set; } }
}
}
namespace IfcBimEditor
{
public sealed class IfcTreeNode
{
public string Type { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public Xbim.Ifc4.Interfaces.IIfcObject Element { get; set; }
public System.Collections.ObjectModel.ObservableCollection<IfcTreeNode> Children { get; set; }
= new System.Collections.ObjectModel.ObservableCollection<IfcTreeNode>();
}
}