xBIM Advanced 02 Insert Copy Function

xBIM Advanced 02 Insert Copy Function

  Merging and deleting entities in the IFC model is a very important task because IFC is not a hierarchical structure. It is a complex structure, has a potential cyclic relationship, and is a two-way navigation. Performing these tasks on a single entity is not a problem (you can think of it as a line in a STEP21 file).

#144= IFCBUILDINGSTOREY('026ajlHVj1HBm_osQm7IDT',#47,'Lower Roof-Slab Level',$,$,#143,$,
                        'Lower Roof-Slab Level',.ELEMENT.,3199.99999999704);

If you want to isolate the complete data island that defines the entity, and you want to delete the entity without side effects on other entities other than the data island, or you want to merge the entity so that it can be mixed with existing data without duplication and inconsistency, It will become more and more difficult. For these reasons, we prefer the third option, which is to choose what you want and copy it into an empty model. This is obviously a potentially complex task, but at least it is easier under your control. IModelThe core functions in the interface are InsertCopy():

T InsertCopy<T>(T toCopy, XbimInstanceHandleMap mappings, PropertyTranformDelegate propTransform, 
                bool includeInverses, bool keepLabels);

Just as a brief description of all parameters:

  • toCopy: the entity to be copied
  • mappings: previously inserted mappings. For all insertions between two models, there should always be only one instance.
  • propTransform: Optional delegate, you can use it to filter the content that will be coppied or transform it before copying. This is a great feature.
  • includeInverses: option to introduce all inverse entities. This is potentially dangerous, because if it is not restricted by the propTransform delegation, it may easily bring almost the entire model.
  • keepLabels: Option to keep the entity label unchanged. Sometimes it can be useful to keep the labels the same. If the target model is not a new model or inserting objects from multiple models, you should never use this option.

It seems a bit mysterious from all these PropertyTranformDelegate delegates. But it is an essential part of the above method because it allows to control the scope of the copied data. If you allow the reverse and do not provide any additional filtering, then you may end up with the original model that contains 98%, even if you are just trying to replicate it on a single wall. To use it correctly, you need to understand the structure of IFC very well. Below is a simple example of a powerful transformation that will ignore all geometric figures and positions, and only allow the description of the inverse relationship between product types and their attributes. Geometry usually accounts for about 90% of the file, so if you are not interested in geometry-based graphics or analysis, you can use it to create very small IFC files that contain only descriptive data.

PropertyTranformDelegate semanticFilter = (property, parentObject) =>
{
   //Omit geometry and position
    if (parentObject is IIfcProduct &&
        (property.PropertyInfo.Name == nameof(IIfcProduct.Representation) ||
        property.PropertyInfo.Name == nameof(IIfcProduct.ObjectPlacement)))
        return null;

   //Omit the mapped geometry
    if (parentObject is IIfcTypeProduct && 
        property.PropertyInfo.Name == nameof(IIfcTypeProduct.RepresentationMaps))
        return null;

   //Only through the reverse relationship (it will take over all attributes and types) to achieve isDefinedby and istypedby
        property.PropertyInfo.Name == nameof(IIfcProduct.IsDefinedBy) ||
        property.PropertyInfo.Name == nameof(IIfcProduct.IsTypedBy)
        ))
        return null;

    return property.PropertyInfo.GetValue(parentObject, null);
};

PropertyTranformDelegate takes two parameters, the first is ExpressMetaProperty, and the other is an object of IPersistEntity. ExpressMetaProperty is a cache object, which is part of our own reflection metamodel, which we use for certain data operations. The delegate is used in other code that uses C# reflection to check the data and copy the value. If you do not specify the delegate insertcopy(), all attributes in the entity will be used and copied.

using Xbim.Common;
using Xbim.Ifc;
using Xbim.Ifc4.Interfaces;

namespace BasicExamples
{
    class InsertCopy
    {
        public void CopyWallsOver()
        {
            const string original = "SampleHouse.ifc";
            const string inserted = "SampleHouseWalls.ifc";

            PropertyTranformDelegate semanticFilter = (property, parentObject) =>
            {
               //Omit geometry and position
                if (parentObject is IIfcProduct &&
                    (property.PropertyInfo.Name == nameof(IIfcProduct.Representation) ||
                    property.PropertyInfo.Name == nameof(IIfcProduct.ObjectPlacement)))
                    return null;

              //Omit the mapped geometry
               if (parentObject is IIfcTypeProduct && 
                    property.PropertyInfo.Name == nameof(IIfcTypeProduct.RepresentationMaps))
                    return null;

               //Only through the reverse relationship (it will take over all attributes and types) to achieve isDefinedby and istypedby
                if (property.EntityAttribute.Order <0 && !(
                    property.PropertyInfo.Name == nameof(IIfcProduct.IsDefinedBy) ||
                    property.PropertyInfo.Name == nameof(IIfcProduct.IsTypedBy)
                    ))
                    return null;

                return property.PropertyInfo.GetValue(parentObject, null);
            };

            using (var model = IfcStore.Open(original))
            {
                var walls = model.Instances.OfType<IIfcWall>();
                using (var iModel = IfcStore.Create(model.IfcSchemaVersion, XbimStoreType.InMemoryModel))
                {
                    using (var txn = iModel.BeginTransaction("Insert copy"))
                    {
                       //All inserts between the two models should use a single graph
                        var map = new XbimInstanceHandleMap(model, iModel);
                        foreach (var wall in walls)
                        {
                            iModel.InsertCopy(wall, map, semanticFilter, true, false);
                        }

                        txn.Commit();
                    }

                    iModel.SaveAs(inserted);
                }
            }
        }
    }
Reference: https://cloud.tencent.com/developer/article/1507747 xBIM Advanced 02 Insert Copy Function-Cloud + Community-Tencent Cloud