IFC model merge and delete entity is a very important task, because IFC is not a hierarchy. It is a complex structure, potentially circular relationship is a two-way navigation. Perform these tasks is not a problem on a single entity (You can think of it as STEP21 line in the 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 silos defined entity, and the entity you want to remove without causing side effects than other entities islands of data, or want to merge the entity to mixing it with the existing data without creating inconsistencies and repeatability, it will become increasingly difficult. For these reasons, we prefer the third option, choose what you want, and copy it to an empty model. This is clearly a potentially complex task, but at least more easily under your control. IModel
Interface core functions are : InsertCopy()
T InsertCopy<T>(T toCopy, XbimInstanceHandleMap mappings, PropertyTranformDelegate propTransform,
bool includeInverses, bool keepLabels);
As for all the parameters are briefly described as :
- toCopy: To copy entities
- Mappings : previously inserted map. For all inserted between the two models should always be only one instance.
- propTransform : Optional delegate, you can use it to filter or conversion will coppied its contents before copying. This is a great feature.
- includeInverses : Option Introduced reverse all entities. This is potentially dangerous, because if unrestricted propTransform commissioned, it could easily bring almost the entire model.
- keepLabels : option to label the entity remains unchanged. Sometimes keeping the same label may be useful. If the target model is not a new model or insert an object from multiple models, you should never use this option.
From all these PropertyTranformDelegate delegate it may seem a bit mysterious. But it is an essential part of the above-described method, since it allows control of the replicated data. If you allow the reverse, and does not provide any additional filtering, you may end up with 98% of the original model included, even if you just try to copy a single wall. To use it correctly, you need a very good understanding of the structure of the IFC. Here is a simple example of a powerful transformation, it will ignore all the geometry and position, allowing only describe inverse relationship between product types and their attributes. Geometry typically accounts for about 90% of the file, so if you can use it or not interested in graphics-based analysis of the geometry to create very small IFC files contain only descriptive data.
SemanticFilter = PropertyTranformDelegate (Property, ParentObject) => { // omitted geometry and position IF (ParentObject IS IIfcProduct && (property.PropertyInfo.Name == NameOf (IIfcProduct.Representation) || property.PropertyInfo.Name == NameOf (IIfcProduct .ObjectPlacement))) return null ; // omitted mapping geometry IF (ParentObject iS IIfcTypeProduct && property.PropertyInfo.Name == NameOf (IIfcTypeProduct.RepresentationMaps)) return null ; //Only the inverse relationship (it will take over all the properties 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 of which is ExpressMetaProperty , the other is IPersistEntity object. ExpressMetaProperty is a cache object, which is part of our own reflective element model, we use some data operations. The delegate to use other code, the code using C # reflection to check the data values and copy. If you do not specify a delegate insertcopy (), all the attributes of the entity will be used and copy them.
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) => { // 省略几何图形和位置 if (parentObject IS IIfcProduct && (property.PropertyInfo.Name == NameOf (IIfcProduct.Representation) || property.PropertyInfo.Name == NameOf (IIfcProduct.ObjectPlacement))) return null ; // omitted mapping geometry IF (ParentObject IS IIfcTypeProduct && property.PropertyInfo.Name == NameOf (IIfcTypeProduct.RepresentationMaps)) return null ; // (it will take over all the properties and types) only by an inverse relationship 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)) { The using ( varTXN = iModel.BeginTransaction ( " the Insert Copy " )) { // all should be inserted between the two models use a single FIG var Map = new new XbimInstanceHandleMap (Model, the iModel); the foreach ( var Wall in Walls) { iModel.InsertCopy (Wall, Map, semanticFilter, to true , to false ); } txn.Commit (); } iModel.SaveAs (inserted The); } } } } }
Reference: http://docs.xbim.net/examples/insert-copy-function.html
2019-06-05