xBimTeam / XbimEssentials

A .NET library to work with data in the IFC format. This is the core component of the Xbim Toolkit
https://xbimteam.github.io/
Other
477 stars 171 forks source link

The IFCSTYLEDITEM attribute is lost when inserting an entity using InsertCopy #527

Closed WZFWork closed 9 months ago

WZFWork commented 9 months ago

Hi, Master

I have just been exposed to XBIM for a short time, and I am not familiar with some objects and methods. Please teach me. I am copying an IfcStore entity to another IfcStore, and all the entity's Ifc styledItem properties are missing.

 Private Function CopyModel() As Boolean
        Dim original As String = "d:\Source2.ifc"
        Dim inserted As String = "d:\Source2Copy.ifc"

        Dim semanticFilter As PropertyTranformDelegate = Function(_property As Xbim.Common.Metadata.ExpressMetaProperty, parentObject As Object)                                                         
                                                             If _property.EntityAttribute.Order < 0 AndAlso
                                                             Not (_property.PropertyInfo.Name = NameOf(IIfcProduct.IsDefinedBy) OrElse
                                                                     _property.PropertyInfo.Name = NameOf(IIfcProduct.IsTypedBy)) Then
                                                                    Return Nothing
                                                             End If
                                                             Return _property.PropertyInfo.GetValue(parentObject, Nothing)
                                                         End Function

        Dim entityPart As List(Of Integer)
        Dim part As IPersistEntity

        Dim newPart As New List(Of IPersistEntity)
        Using model = IfcStore.Open(original)
            Dim entity As IEnumerable(Of IIfcElementAssembly) = model.Instances.OfType(Of IIfcElementAssembly)()

            Using iModel = IfcStore.Create(XbimSchemaVersion.Ifc2X3, XbimStoreType.InMemoryModel)
                Using txn = iModel.BeginTransaction("Insert copy")
                    Dim map = New XbimInstanceHandleMap(model, iModel)

                    For Each e In entity
                        entityPart = FindPartOfAssembly(model, e.EntityLabel)
                        For Each a In entityPart
                            part = model.Instances(a)
                            newPart.Add(iModel.InsertCopy(part, map, semanticFilter, True, True))
                        Next
                    Next

                    txn.Commit()
                End Using

                iModel.SaveAs(inserted)
            End Using
        End Using

        Return True
    End Function

    Private Function FindPartOfAssembly(ByVal _model As IfcStore, ByVal entityLabel As Integer) As List(Of Integer)
        Dim entity As Object = _model.Instances(entityLabel)
        Return entity.IsDecomposedBy.SelectMany(Function(r) r.RelatedObjects).Select(Function(p) p.EntityLabel).ToList
    End Function

I know the problem lies in the semanticFilter delegate function, but I don't know how to reflect IfcstyledItem.

I hope someone can answer, thank you in advance.

andyward commented 9 months ago

My guess is that you're missing an inverse - likely the StyledByItem inverse on the GeometryRepresentationItem.

The semantic filter delegate is filtering out all inverses except for IsTypedBy and IsDefinedBy. This would exclude the StyledByItem inverse relationship. You may also need to account for other representations (like MappedRepresentation)

I find Xbim Xplorer a handy tool to understand these relationships in your model - alongside the IFC documentation - Xplorer lets you follow the hyperlinks in the properties to see the Ifc structure:

image

e.g. see the diagram (Fig 366) at https://standards.buildingsmart.org/IFC/RELEASE/IFC4/ADD1/HTML/link/ifcstyleditem.htm

You'll see the properties window shows the IfcFacetetBrep for a Wall which I navigated to via:

IfcWall.Representation-> IfcProductDefinitionShape -> IfcShapeRepresentation -> IfcFacetedBrep (subclass of IfcGeometricRepresentationItem) ====> StyledByItem

This last step is an 'Inverse' relationship. ie. like a many-many table in a database. So the predicate needs to be extended to allow this part of the IFC graph to be copied.

Try changing the delegate to something like this:


If _property.EntityAttribute.Order < 0 AndAlso
     Not (_property.PropertyInfo.Name = NameOf(IIfcProduct.IsDefinedBy) OrElse
         _property.PropertyInfo.Name = NameOf(IIfcProduct.IsTypedBy) OrElse
         _property.PropertyInfo.Name = NameOf(IIfcRepresentationItem.StyledByItem) ) Then
      Return Nothing
End If
Return _property.PropertyInfo.GetValue(parentObject, Nothing)
WZFWork commented 9 months ago

Thank you very much for the detailed answer from Andy. The Xbim Xplorer tool is very easy to use,I am using this tool to improve my understanding of the structure of IFC. Thank you again for taking time out of your busy schedule to answer my questions, Master.