0

我有一个 IFC 格式的 BIM 模型,我想使用 Xbim 为模型中的每个对象添加一个新属性,比如成本。我正在构建一个 .NET 应用程序。以下代码运行良好,除了该属性还添加到楼层、建筑物和场地 - 我只想将其添加到不嵌套其他对象的最低级别对象。

首先,我尝试了各种方法来打印每个对象的“相关对象”,认为我可以过滤掉任何具有非空相关对象的对象。这让我看到了这个:

IfcRelDefinesByType.RelatedObjects ( http://docs.xbim.net/XbimDocs/html/7fb93e55-dcf7-f6da-0e08-f8b5a70accf2.htm ) 认为相关对象 ( https://standards.buildingsmart.org/IFC/RELEASE/IFC2x3 /FINAL/HTML/ifckernel/lexical/ifcreldecomposes.htm)将包含此信息。

但是我还没有设法从这个文档中实现工作代码。

这是我的代码:

using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using Xbim.Ifc;
using Xbim.Ifc2x3.Interfaces;
using Xbim.Ifc4.Kernel;
using Xbim.Ifc4.MeasureResource;
using Xbim.Ifc4.PropertyResource;
using Xbim.Ifc4.Interfaces;
using IIfcProject = Xbim.Ifc4.Interfaces.IIfcProject;

namespace MyPlugin0._1
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            outputBox.AppendText("Plugin launched successfully");
        }


        private void button1_Click(object sender, EventArgs e)
        {
            // Setup the editor
            var editor = new XbimEditorCredentials
            {
                ApplicationDevelopersName = "O",
                ApplicationFullName = "MyPlugin",
                ApplicationIdentifier = "99990100",
                ApplicationVersion = "0.1",
                EditorsFamilyName = "B",
                EditorsGivenName = "O",
                EditorsOrganisationName = "MyWorkplace"
            };

            // Choose an IFC file to work with        
            OpenFileDialog dialog = new OpenFileDialog();
            dialog.ShowDialog();
            string filename = dialog.FileName;
            string newLine = Environment.NewLine;
            
            // Check if the file is valid and continue
            if (!filename.ToLower().EndsWith(".ifc"))
            {
                // Output error if the file is the wrong format
                outputBox.AppendText(newLine + "Error: select an .ifc-file");
            }
            else
            {
                // Open the selected file (## Not sure what the response is to a corrupt/invalid .ifc-file)
                using (var model = IfcStore.Open(filename, editor, 1.0))
                {
                    // Output success when the file has been opened
                    string reversedName = Form1.ReversedString(filename);
                    int filenameShortLength = reversedName.IndexOf("\\");
                    string filenameShort = filename.Substring(filename.Length - filenameShortLength, filenameShortLength);
                    outputBox.AppendText(newLine + filenameShort + " opened successfully for editing");

                    

                    ////////////////////////////////////////////////////////////////////
                    // Get all the objects in the model ( ### lowest level only??? ###)
                    var objs = model.Instances.OfType<IfcObjectDefinition>();
                    ////////////////////////////////////////////////////////////////////



                    // Create and store a new property
                    using (var txn = model.BeginTransaction("Store Costs"))
                    {
                        // Iterate over all the walls to initiate the Point Source property
                        foreach (var obj in objs)
                        {

                            // Create new property set to host properties
                            var pSetRel = model.Instances.New<IfcRelDefinesByProperties>(r =>
                            {
                                r.GlobalId = Guid.NewGuid();
                                r.RelatingPropertyDefinition = model.Instances.New<IfcPropertySet>(pSet =>
                                {
                                    pSet.Name = "Economy";
                                    pSet.HasProperties.Add(model.Instances.New<IfcPropertySingleValue>(p =>
                                    {
                                        p.Name = "Cost";
                                        p.NominalValue = new IfcMonetaryMeasure(200.00); // Default Currency set on IfcProject
                                    }));
                                });
                            });

                            // Add property to the object
                            pSetRel.RelatedObjects.Add(obj);

                            // Rename the object
                            outputBox.AppendText(newLine + "Cost property added to " + obj.Name);
                            obj.Name += "_withCost";

                            
                            //outputBox.AppendText(newLine + obj.OwnerHistory.ToString());
                            
                        }

                        // Commit changes to this model
                        txn.Commit();
                    };

                    // Save the changed model with a new name. Does not overwrite existing files but generates a unique name
                    string newFilename = filenameShort.Substring(0, filenameShort.Length - 4) + "_Modified.IFC";
                    int i = 1;
                    while (File.Exists(newFilename))
                    {
                        newFilename = filenameShort.Substring(0, filenameShort.Length - 4) + "_Modified(" + i.ToString() + ").IFC";
                        i += 1;
                    }
                    model.SaveAs(newFilename); // (!) Gets stored in the project folder > bin > Debug
                    outputBox.AppendText(newLine + newFilename + " has been saved");
                       
                };
            }
            
        }



        // Reverse string-function
        static string ReversedString(string text)
        {
            if (text == null) return null;
            char[] array = text.ToCharArray();
            Array.Reverse(array);
            return new String(array);
        }


        private void Form1_Load(object sender, EventArgs e)
        {

        }


        
    }
}
4

1 回答 1

0

You're starting out by getting too broad a set of elements in the model. Pretty much everything in an IFC model will be classed as (or 'derived from') an instance of IfcObjectDefinition - including Spatial concepts (spaces, levels, zones etc) as well as more abstract concepts of Actors (people), Resources and the like.

You'd be better off filtering down objs to the more specific types such as IfcElement, IfcBuildingElement - or even the more real world elements below (IfcWindow, IfcDoor etc.)

// Get all the building elements in the model 
var objs = model.Instances.OfType<IfcBuildingElement>();

You could also filter by more specific clauses more than just their type by using the other IFC relationships.

于 2020-07-20T13:36:55.053 回答