public IfcElementSignature(IfcElement elem, Xbim3DModelContext geometryContext)
        {
            XbimMatrix3D m3D = XbimMatrix3D.Identity;

            if (elem.ObjectPlacement != null)
            {
                m3D = elem.ObjectPlacement.ToMatrix3D();
            }
            var geomManager = elem.ModelOf.GeometryManager;

            ShapeId = 0;
            //get the 3D shape
            var shapes = geometryContext.ShapeInstancesOf(elem);

            if (shapes.Any())
            {
                XbimRect3D r3D = XbimRect3D.Empty;
                foreach (var shape in shapes)
                {
                    if (r3D.IsEmpty)
                    {
                        r3D = shape.BoundingBox;
                    }
                    else
                    {
                        r3D.Union(shape.BoundingBox);
                    }
                }
                XbimPoint3D p3D = r3D.Centroid();
                p3D = m3D.Transform(p3D);
                BoundingSphereRadius = r3D.Length() / 2;
                CentroidX            = p3D.X;
                CentroidY            = p3D.Y;
                CentroidZ            = p3D.Z;
            }
            //get the defining type
            IfcTypeObject     ot       = elem.GetDefiningType();
            IfcMaterialSelect material = elem.GetMaterial();
            //sort out property definitions
            List <IfcPropertySet> psets = elem.GetAllPropertySets();

            PropertyCount = psets.SelectMany(p => p.HasProperties).Count();
            psets.Sort(new PropertySetNameComparer());
            foreach (var pset in psets)
            {
                PropertySetNamesKey ^= pset.Name.GetHashCode();
            }
            List <IfcPropertySingleValue> props = psets.SelectMany(p => p.HasProperties).OfType <IfcPropertySingleValue>().ToList();

            props.Sort(new PropertySingleValueNameComparer());
            foreach (var prop in props)
            {
                PropertyNamesKey ^= prop.Name.GetHashCode();
            }
            props.Sort(new PropertySingleValueValueComparer());
            foreach (var prop in props)
            {
                PropertyValuesKey ^= prop.NominalValue.GetHashCode();
            }
            ModelID       = elem.EntityLabel;
            SchemaType    = elem.GetType().Name;
            DefinedTypeId = (ot == null ? "" : ot.GlobalId.ToPart21);
            GlobalId      = elem.GlobalId;
            OwningUser    = elem.OwnerHistory.LastModifyingUser != null?elem.OwnerHistory.LastModifyingUser.ToString() : elem.OwnerHistory.OwningUser.ToString();

            Name               = elem.Name ?? "";
            Description        = elem.Description ?? "";
            HasAssignmentsKey  = elem.HasAssignments.Count();
            IsDecomposedByKey  = elem.IsDecomposedBy.Count();
            DecomposesKey      = elem.Decomposes.Count();
            HasAssociationsKey = elem.HasAssociations.Count();
            ObjectType         = elem.ObjectType ?? "";
            MaterialName       = material == null ? "" : material.Name;
            ReferencedByKey    = elem.ReferencedBy.Count();
            Tag = elem.Tag ?? "";
            HasStructuralMemberKey    = elem.HasStructuralMember.Count();
            FillsVoidsKey             = elem.FillsVoids.Count();
            ConnectedToKey            = elem.ConnectedTo.Count();
            HasCoveringsKey           = elem.HasCoverings.Count();
            HasProjectionsKey         = elem.HasProjections.Count();
            ReferencedInStructuresKey = elem.ReferencedInStructures.Count();
            HasPortsKey                = elem.HasPorts.Count();
            HasOpeningsKey             = elem.HasOpenings.Count();
            IsConnectionRealizationKey = elem.IsConnectionRealization.Count();
            ProvidesBoundariesKey      = elem.ProvidesBoundaries.Count();
            ConnectedFromKey           = elem.ConnectedFrom.Count();
            ContainedInStructureKey    = elem.ContainedInStructure.Count();
        }