/// <summary>
 /// The constructor for the class.
 /// </summary>
 /// <param name="rebarElement">The element that created the rebar.</param>
 /// <param name="elementHandle">The associated IFC element handle.</param>
 /// <param name="levelInfo">The information for the associated level.</param>
 public DelayedProductWrapper(Element rebarElement, IFCAnyHandle elementHandle, IFCLevelInfo levelInfo)
 {
    RebarElement = rebarElement;
    ElementHandle = elementHandle;
    LevelInfo = levelInfo;
 }
Example #2
0
        /// <summary>
        /// Calculates the distance to the next level if the UpToLevel parameter is set.
        /// If the parameter is not set, or the distance is negative, 0 is returned.
        /// This is not set in IFCLevelInfo as we want this calculation to be done in .NET code.
        /// </summary>
        /// <param name="level">
        /// The Level.
        /// </param>
        public static double calculateDistanceToNextLevel(Document doc, ElementId levelId, IFCLevelInfo levelInfo)
        {
            double    height      = 0.0;
            Level     level       = doc.GetElement(levelId) as Level;
            ElementId nextLevelId = ElementId.InvalidElementId;

            if (level != null)
            {
                Parameter nextLevelParameter = level.get_Parameter(BuiltInParameter.LEVEL_UP_TO_LEVEL);
                if (nextLevelParameter != null)
                {
                    Element nextLevelAsElement = doc.GetElement(nextLevelParameter.AsElementId());
                    if (nextLevelAsElement != null)
                    {
                        Level possibleNextLevel = nextLevelAsElement as Level;
                        if (possibleNextLevel != null && IsBuildingStory(possibleNextLevel))
                        {
                            double nextLevelElevation = possibleNextLevel.Elevation;
                            double netElevation       = nextLevelElevation - level.Elevation;
                            if (netElevation > 0.0)
                            {
                                height      = netElevation;
                                nextLevelId = nextLevelParameter.AsElementId();
                            }
                        }
                    }
                }
            }

            if ((height <= 0.0) && (levelInfo != null))
            {
                height = levelInfo.DistanceToNextLevel;
            }

            ExporterCacheManager.LevelInfoCache.Register(levelId, nextLevelId, height);
            return(height);
        }
        /// <summary>
        /// Gets the height of a spatial element.
        /// </summary>
        /// <param name="spatialElement">
        /// The spatial element.
        /// </param>
        /// <param name="scale">
        /// The scale value.
        /// </param>
        /// <param name="levelInfo">
        /// The level info.
        /// </param>
        /// <returns>
        /// The height.
        /// </returns>
        static double GetHeight(SpatialElement spatialElement, double scale, ElementId levelId, IFCLevelInfo levelInfo)
        {
            Document document = spatialElement.Document;

            ElementId topLevelId;
            ParameterUtil.GetElementIdValueFromElement(spatialElement, BuiltInParameter.ROOM_UPPER_LEVEL, out topLevelId);

            double topOffset;
            ParameterUtil.GetDoubleValueFromElement(spatialElement, BuiltInParameter.ROOM_UPPER_OFFSET, out topOffset);

            double bottomOffset;
            ParameterUtil.GetDoubleValueFromElement(spatialElement, BuiltInParameter.ROOM_LOWER_OFFSET, out bottomOffset);

            Level bottomLevel = document.GetElement(levelId) as Level;
            Level topLevel =
               (levelId == topLevelId) ? bottomLevel : document.GetElement(topLevelId) as Level;

            double roomHeight = 0.0;
            if (bottomLevel != null && topLevel != null)
            {
                roomHeight = (topLevel.Elevation - bottomLevel.Elevation) + (topOffset - bottomOffset);
                roomHeight *= scale;
            }

            if (MathUtil.IsAlmostZero(roomHeight))
            {
                double levelHeight = ExporterCacheManager.LevelInfoCache.FindHeight(levelId);
                if (levelHeight < 0.0)
                    levelHeight = LevelUtil.calculateDistanceToNextLevel(document, levelId, levelInfo);

                roomHeight = levelHeight * scale;
            }

            // For area spaces, we assign a dummy height (1'), as we are not allowed to export IfcSpaces without a volumetric representation.
            if (MathUtil.IsAlmostZero(roomHeight) && spatialElement is Area)
            {
                roomHeight = 1.0;
            }

            return roomHeight;
        }
        /// <summary>
        /// Gets the height of a spatial element.
        /// </summary>
        /// <param name="spatialElement">The spatial element.</param>
        /// <param name="levelId">The level id.</param>
        /// <param name="levelInfo">The level info.</param>
        /// <returns>
        /// The height, scaled in IFC units.
        /// </returns>
        static double GetScaledHeight(SpatialElement spatialElement, ElementId levelId, IFCLevelInfo levelInfo)
        {
            Document document = spatialElement.Document;
            bool isArea = spatialElement is Area;

            ElementId topLevelId = ElementId.InvalidElementId;
            double topOffset = 0.0;

            // These values are internally set for areas, but are invalid.  Ignore them and just use the level height.
            if (!isArea)
            {
                ParameterUtil.GetElementIdValueFromElement(spatialElement, BuiltInParameter.ROOM_UPPER_LEVEL, out topLevelId);
                ParameterUtil.GetDoubleValueFromElement(spatialElement, BuiltInParameter.ROOM_UPPER_OFFSET, out topOffset);
            }

            double bottomOffset;
            ParameterUtil.GetDoubleValueFromElement(spatialElement, BuiltInParameter.ROOM_LOWER_OFFSET, out bottomOffset);

            Level bottomLevel = document.GetElement(levelId) as Level;
            Level topLevel =
               (levelId == topLevelId) ? bottomLevel : document.GetElement(topLevelId) as Level;

            double roomHeight = 0.0;
            if (bottomLevel != null && topLevel != null)
            {
                roomHeight = (topLevel.Elevation - bottomLevel.Elevation) + (topOffset - bottomOffset);
                roomHeight = UnitUtil.ScaleLength(roomHeight);
            }

            if (MathUtil.IsAlmostZero(roomHeight))
            {
                double levelHeight = ExporterCacheManager.LevelInfoCache.FindHeight(levelId);
                if (levelHeight < 0.0)
                    levelHeight = LevelUtil.CalculateDistanceToNextLevel(document, levelId, levelInfo);

                roomHeight = UnitUtil.ScaleLength(levelHeight);
            }

            // For area spaces, we assign a dummy height (1 unit), as we are not allowed to export IfcSpaces without a volumetric representation.
            if (MathUtil.IsAlmostZero(roomHeight) && spatialElement is Area)
            {
                roomHeight = 1.0;
            }

            return roomHeight;
        }
        /// <summary>
        /// Exports an element as an IFC assembly.
        /// </summary>
        /// <param name="exporterIFC">The ExporterIFC object.</param>
        /// <param name="element">The element.</param>
        /// <param name="productWrapper">The ProductWrapper.</param>
        /// <returns>True if exported successfully, false otherwise.</returns>
        public static bool ExportAssemblyInstanceElement(ExporterIFC exporterIFC, AssemblyInstance element,
                                                         ProductWrapper productWrapper)
        {
            if (element == null)
            {
                return(false);
            }

            IFCFile file = exporterIFC.GetFile();

            using (IFCTransaction tr = new IFCTransaction(file))
            {
                IFCAnyHandle assemblyInstanceHnd = null;

                string          guid            = GUIDUtil.CreateGUID(element);
                IFCAnyHandle    ownerHistory    = ExporterCacheManager.OwnerHistoryHandle;
                IFCAnyHandle    localPlacement  = null;
                PlacementSetter placementSetter = null;
                IFCLevelInfo    levelInfo       = null;
                bool            relateToLevel   = true;

                string            ifcEnumType;
                IFCExportInfoPair exportAs = ExporterUtil.GetExportType(exporterIFC, element, out ifcEnumType);
                if (exportAs.ExportInstance == IFCEntityType.IfcSystem)
                {
                    string name        = NamingUtil.GetNameOverride(element, NamingUtil.GetIFCName(element));
                    string description = NamingUtil.GetDescriptionOverride(element, null);
                    string objectType  = NamingUtil.GetObjectTypeOverride(element, NamingUtil.GetFamilyAndTypeName(element));
                    assemblyInstanceHnd = IFCInstanceExporter.CreateSystem(file, guid, ownerHistory, name, description, objectType);

                    // Create classification reference when System has classification filed name assigned to it
                    ClassificationUtil.CreateClassification(exporterIFC, file, element, assemblyInstanceHnd);

                    HashSet <IFCAnyHandle> relatedBuildings = new HashSet <IFCAnyHandle>();
                    relatedBuildings.Add(ExporterCacheManager.BuildingHandle);

                    IFCAnyHandle relServicesBuildings = IFCInstanceExporter.CreateRelServicesBuildings(file, GUIDUtil.CreateGUID(),
                                                                                                       ExporterCacheManager.OwnerHistoryHandle, null, null, assemblyInstanceHnd, relatedBuildings);

                    relateToLevel = false; // Already related to the building via IfcRelServicesBuildings.
                }
                else
                {
                    using (placementSetter = PlacementSetter.Create(exporterIFC, element))
                    {
                        IFCAnyHandle representation = null;

                        // We have limited support for exporting assemblies as other container types.
                        localPlacement = placementSetter.LocalPlacement;
                        levelInfo      = placementSetter.LevelInfo;

                        switch (exportAs.ExportInstance)
                        {
                        case IFCEntityType.IfcCurtainWall:
                            //case IFCExportType.IfcCurtainWallType:
                            //string cwPredefinedType = IFCValidateEntry.GetValidIFCPredefinedType(element, ifcEnumType, "IfcCurtainWallType");
                            assemblyInstanceHnd = IFCInstanceExporter.CreateCurtainWall(exporterIFC, element, guid,
                                                                                        ownerHistory, localPlacement, representation, ifcEnumType);
                            break;

                        case IFCEntityType.IfcRamp:
                            string rampPredefinedType = RampExporter.GetIFCRampType(ifcEnumType);
                            //rampPredefinedType = IFCValidateEntry.GetValidIFCPredefinedType(element, rampPredefinedType, "IfcRampType");
                            assemblyInstanceHnd = IFCInstanceExporter.CreateRamp(exporterIFC, element, guid,
                                                                                 ownerHistory, localPlacement, representation, rampPredefinedType);
                            break;

                        case IFCEntityType.IfcRoof:
                            //string roofPredefinedType = IFCValidateEntry.GetValidIFCPredefinedType(element, ifcEnumType, "IfcRoofType");
                            assemblyInstanceHnd = IFCInstanceExporter.CreateRoof(exporterIFC, element, guid,
                                                                                 ownerHistory, localPlacement, representation, ifcEnumType);
                            break;

                        case IFCEntityType.IfcStair:
                            string stairPredefinedType = StairsExporter.GetIFCStairType(ifcEnumType);
                            //stairPredefinedType = IFCValidateEntry.GetValidIFCPredefinedType(element, stairPredefinedType, "IfcStairType");
                            assemblyInstanceHnd = IFCInstanceExporter.CreateStair(exporterIFC, element, guid,
                                                                                  ownerHistory, localPlacement, representation, stairPredefinedType);
                            break;

                        case IFCEntityType.IfcWall:
                            //string wallPredefinedType = IFCValidateEntry.GetValidIFCPredefinedType(element, ifcEnumType, "IfcWallType");
                            assemblyInstanceHnd = IFCInstanceExporter.CreateWall(exporterIFC, element, guid,
                                                                                 ownerHistory, localPlacement, representation, ifcEnumType);
                            break;

                        default:
                            string objectType = NamingUtil.GetObjectTypeOverride(element, NamingUtil.GetFamilyAndTypeName(element));
                            IFCElementAssemblyType assemblyPredefinedType = GetPredefinedTypeFromObjectType(objectType);
                            assemblyInstanceHnd = IFCInstanceExporter.CreateElementAssembly(exporterIFC, element, guid,
                                                                                            ownerHistory, localPlacement, representation, IFCAssemblyPlace.NotDefined, assemblyPredefinedType);
                            break;
                        }
                    }
                }

                if (assemblyInstanceHnd == null)
                {
                    return(false);
                }

                // relateToLevel depends on how the AssemblyInstance is being mapped to IFC, above.
                productWrapper.AddElement(element, assemblyInstanceHnd, levelInfo, null, relateToLevel);

                ExporterCacheManager.AssemblyInstanceCache.RegisterAssemblyInstance(element.Id, assemblyInstanceHnd);

                tr.Commit();
                return(true);
            }
        }
Example #6
0
 /// <summary>
 /// Add a space to the wrapper, with associated level and extrusion data information.
 /// </summary>
 /// <param name="handle">The element handle.</param>
 /// <param name="levelInfo">The level information.</param>
 /// <param name="data">The extrusion creation data (can be null.)</param>
 /// <param name="relateToLevel">Relate to the level in the setter, or not.</param>
 public void AddSpace(IFCAnyHandle handle, IFCLevelInfo levelInfo, IFCExtrusionCreationData data, bool relateToLevel)
 {
     m_InternalWrapper.AddSpace(handle, levelInfo, data, relateToLevel);
 }
 /// <summary>
 /// Adds an annotation handle to associate with the IfcProduct in this wrapper.
 /// </summary>
 /// <param name="handle">The annotation handle.</param>
 /// <param name="levelInfo">The level information, can be null if relateToLevel is false.</param>
 /// <param name="relateToLevel">Whether the annotation is contained in a level.</param>
 public void AddAnnotation(IFCAnyHandle handle, IFCLevelInfo levelInfo, bool relateToLevel)
 {
    // The internal AddAnnotation takes an optional levelInfo, so we don't need to do a levelInfo null check here.
    m_InternalWrapper.AddAnnotation(handle, levelInfo, relateToLevel);
 }
Example #8
0
        /// <summary>
        /// Exports the top stories of a multistory ramp.
        /// </summary>
        /// <param name="exporterIFC">The ExporterIFC object.</param>
        /// <param name="ramp">The ramp element.</param>
        /// <param name="numFlights">The number of flights for a multistory ramp.</param>
        /// <param name="rampHnd">The stairs container handle.</param>
        /// <param name="components">The components handles.</param>
        /// <param name="ecData">The extrusion creation data.</param>
        /// <param name="componentECData">The extrusion creation data for the components.</param>
        /// <param name="placementSetter">The placement setter.</param>
        /// <param name="productWrapper">The ProductWrapper.</param>
        public static void ExportMultistoryRamp(ExporterIFC exporterIFC, Element ramp, int numFlights,
                                                IFCAnyHandle rampHnd, IList <IFCAnyHandle> components, IList <IFCExtrusionCreationData> componentECData,
                                                PlacementSetter placementSetter, ProductWrapper productWrapper)
        {
            if (numFlights < 2)
            {
                return;
            }

            double heightNonScaled = GetRampHeight(exporterIFC, ramp);

            if (heightNonScaled < MathUtil.Eps())
            {
                return;
            }

            if (IFCAnyHandleUtil.IsNullOrHasNoValue(rampHnd))
            {
                return;
            }

            IFCAnyHandle localPlacement = IFCAnyHandleUtil.GetObjectPlacement(rampHnd);

            if (IFCAnyHandleUtil.IsNullOrHasNoValue(localPlacement))
            {
                return;
            }

            IFCAnyHandle ownerHistory = ExporterCacheManager.OwnerHistoryHandle;

            IFCFile file = exporterIFC.GetFile();

            IFCAnyHandle   relPlacement = GeometryUtil.GetRelativePlacementFromLocalPlacement(localPlacement);
            IFCAnyHandle   ptHnd        = IFCAnyHandleUtil.GetLocation(relPlacement);
            IList <double> origCoords   = IFCAnyHandleUtil.GetCoordinates(ptHnd);

            IList <IFCAnyHandle> rampLocalPlacementHnds = new List <IFCAnyHandle>();
            IList <IFCLevelInfo> levelInfos             = new List <IFCLevelInfo>();

            for (int ii = 0; ii < numFlights - 1; ii++)
            {
                IFCAnyHandle newLevelHnd = null;

                // We are going to avoid internal scaling routines, and instead scale in .NET.
                double       newOffsetUnscaled = 0.0;
                IFCLevelInfo currLevelInfo     =
                    placementSetter.GetOffsetLevelInfoAndHandle(heightNonScaled * (ii + 1), 1.0, ramp.Document, out newLevelHnd, out newOffsetUnscaled);
                double newOffsetScaled = UnitUtil.ScaleLength(newOffsetUnscaled);

                if (currLevelInfo != null)
                {
                    levelInfos.Add(currLevelInfo);
                }
                else
                {
                    levelInfos.Add(placementSetter.LevelInfo);
                }

                XYZ orig;
                if (ptHnd.HasValue)
                {
                    orig = new XYZ(origCoords[0], origCoords[1], newOffsetScaled);
                }
                else
                {
                    orig = new XYZ(0.0, 0.0, newOffsetScaled);
                }

                rampLocalPlacementHnds.Add(ExporterUtil.CreateLocalPlacement(file, newLevelHnd, orig, null, null));
            }

            IList <List <IFCAnyHandle> > newComponents = new List <List <IFCAnyHandle> >();

            for (int ii = 0; ii < numFlights - 1; ii++)
            {
                newComponents.Add(new List <IFCAnyHandle>());
            }

            int       compIdx = 0;
            ElementId catId   = CategoryUtil.GetSafeCategoryId(ramp);

            foreach (IFCAnyHandle component in components)
            {
                string       componentName        = IFCAnyHandleUtil.GetStringAttribute(component, "Name");
                string       componentDescription = IFCAnyHandleUtil.GetStringAttribute(component, "Description");
                string       componentObjectType  = IFCAnyHandleUtil.GetStringAttribute(component, "ObjectType");
                string       componentElementTag  = IFCAnyHandleUtil.GetStringAttribute(component, "Tag");
                IFCAnyHandle componentProdRep     = IFCAnyHandleUtil.GetInstanceAttribute(component, "Representation");

                IList <string>       localComponentNames    = new List <string>();
                IList <IFCAnyHandle> componentPlacementHnds = new List <IFCAnyHandle>();

                IFCAnyHandle localLocalPlacement    = IFCAnyHandleUtil.GetObjectPlacement(component);
                IFCAnyHandle localRelativePlacement =
                    (localLocalPlacement == null) ? null : IFCAnyHandleUtil.GetInstanceAttribute(localLocalPlacement, "RelativePlacement");

                bool isSubRamp = component.IsSubTypeOf(IFCEntityType.IfcRamp.ToString());
                for (int ii = 0; ii < numFlights - 1; ii++)
                {
                    localComponentNames.Add((componentName == null) ? (ii + 2).ToString() : (componentName + ":" + (ii + 2)));
                    if (isSubRamp)
                    {
                        componentPlacementHnds.Add(ExporterUtil.CopyLocalPlacement(file, rampLocalPlacementHnds[ii]));
                    }
                    else
                    {
                        componentPlacementHnds.Add(IFCInstanceExporter.CreateLocalPlacement(file, rampLocalPlacementHnds[ii], localRelativePlacement));
                    }
                }

                IList <IFCAnyHandle> localComponentHnds = new List <IFCAnyHandle>();
                if (isSubRamp)
                {
                    string componentType = IFCAnyHandleUtil.GetEnumerationAttribute(component, ExporterCacheManager.ExportOptionsCache.ExportAs4 ? "PredefinedType" : "ShapeType");
                    string localRampType = GetIFCRampType(componentType);

                    for (int ii = 0; ii < numFlights - 1; ii++)
                    {
                        IFCAnyHandle representationCopy =
                            ExporterUtil.CopyProductDefinitionShape(exporterIFC, ramp, catId, componentProdRep);

                        localComponentHnds.Add(IFCInstanceExporter.CreateRamp(file, GUIDUtil.CreateGUID(), ownerHistory,
                                                                              localComponentNames[ii], componentDescription, componentObjectType, componentPlacementHnds[ii], representationCopy,
                                                                              componentElementTag, localRampType));
                    }
                }
                else if (IFCAnyHandleUtil.IsSubTypeOf(component, IFCEntityType.IfcRampFlight))
                {
                    for (int ii = 0; ii < numFlights - 1; ii++)
                    {
                        IFCAnyHandle representationCopy =
                            ExporterUtil.CopyProductDefinitionShape(exporterIFC, ramp, catId, componentProdRep);

                        localComponentHnds.Add(IFCInstanceExporter.CreateRampFlight(file, GUIDUtil.CreateGUID(), ownerHistory,
                                                                                    localComponentNames[ii], componentDescription, componentObjectType, componentPlacementHnds[ii], representationCopy,
                                                                                    componentElementTag, "NOTDEFINED"));
                    }
                }
                else if (IFCAnyHandleUtil.IsSubTypeOf(component, IFCEntityType.IfcSlab))
                {
                    string      componentType    = IFCAnyHandleUtil.GetEnumerationAttribute(component, "PredefinedType");
                    IFCSlabType localLandingType = FloorExporter.GetIFCSlabType(componentType);

                    for (int ii = 0; ii < numFlights - 1; ii++)
                    {
                        IFCAnyHandle representationCopy =
                            ExporterUtil.CopyProductDefinitionShape(exporterIFC, ramp, catId, componentProdRep);

                        localComponentHnds.Add(IFCInstanceExporter.CreateSlab(file, GUIDUtil.CreateGUID(), ownerHistory,
                                                                              localComponentNames[ii], componentDescription, componentObjectType, componentPlacementHnds[ii], representationCopy,
                                                                              componentElementTag, localLandingType.ToString()));
                    }
                }
                else if (IFCAnyHandleUtil.IsSubTypeOf(component, IFCEntityType.IfcMember))
                {
                    for (int ii = 0; ii < numFlights - 1; ii++)
                    {
                        IFCAnyHandle representationCopy =
                            ExporterUtil.CopyProductDefinitionShape(exporterIFC, ramp, catId, componentProdRep);

                        localComponentHnds.Add(IFCInstanceExporter.CreateMember(file, GUIDUtil.CreateGUID(), ownerHistory,
                                                                                localComponentNames[ii], componentDescription, componentObjectType, componentPlacementHnds[ii], representationCopy,
                                                                                componentElementTag, "STRINGER"));
                    }
                }

                for (int ii = 0; ii < numFlights - 1; ii++)
                {
                    if (localComponentHnds[ii] != null)
                    {
                        newComponents[ii].Add(localComponentHnds[ii]);
                        productWrapper.AddElement(null, localComponentHnds[ii], levelInfos[ii], componentECData[compIdx], false);
                    }
                }
                compIdx++;
            }

            // finally add a copy of the container.
            IList <IFCAnyHandle> rampCopyHnds = new List <IFCAnyHandle>();

            for (int ii = 0; ii < numFlights - 1; ii++)
            {
                string rampName         = IFCAnyHandleUtil.GetStringAttribute(rampHnd, "Name");
                string rampObjectType   = IFCAnyHandleUtil.GetStringAttribute(rampHnd, "ObjectType");
                string rampDescription  = IFCAnyHandleUtil.GetStringAttribute(rampHnd, "Description");
                string rampElementTag   = IFCAnyHandleUtil.GetStringAttribute(rampHnd, "Tag");
                string rampTypeAsString = null;
                if (ExporterCacheManager.ExportOptionsCache.ExportAs4)
                {
                    rampTypeAsString = IFCAnyHandleUtil.GetEnumerationAttribute(rampHnd, "PredefinedType");
                }
                else
                {
                    rampTypeAsString = IFCAnyHandleUtil.GetEnumerationAttribute(rampHnd, "ShapeType");
                }
                string rampType = GetIFCRampType(rampTypeAsString);

                string containerRampName = rampName + ":" + (ii + 2);
                rampCopyHnds.Add(IFCInstanceExporter.CreateRamp(file, GUIDUtil.CreateGUID(), ownerHistory,
                                                                containerRampName, rampDescription, rampObjectType, rampLocalPlacementHnds[ii], null, rampElementTag, rampType));

                productWrapper.AddElement(ramp, rampCopyHnds[ii], levelInfos[ii], null, true);
            }

            for (int ii = 0; ii < numFlights - 1; ii++)
            {
                StairRampContainerInfo stairRampInfo = new StairRampContainerInfo(rampCopyHnds[ii], newComponents[ii],
                                                                                  rampLocalPlacementHnds[ii]);
                ExporterCacheManager.StairRampContainerInfoCache.AppendStairRampContainerInfo(ramp.Id, stairRampInfo);
            }
        }
 /// <summary>
 /// Add a generic element to the wrapper, with associated level and extrusion data information, and create associated internal property sets if option is set.
 /// </summary>
 /// <param name="element">The element.</param>
 /// <param name="handle">The element handle.</param>
 /// <param name="levelInfo">The level information.</param>
 /// <param name="data">The extrusion creation data (can be null.)</param>
 /// <param name="relateToLevel">Relate to the level in the setter, or not.</param>
 public void AddElement(Element element, IFCAnyHandle handle, IFCLevelInfo levelInfo, IFCExtrusionCreationData data, bool relateToLevel)
 {
    // There is a bug in the internal AddElement that requires us to do a levelInfo null check here.
    bool actuallyRelateToLevel = relateToLevel && (levelInfo != null);
    m_InternalWrapper.AddElement(handle, levelInfo, data, actuallyRelateToLevel);
    if (levelInfo == null && relateToLevel)
       ExporterCacheManager.LevelInfoCache.OrphanedElements.Add(handle);
    RegisterHandleWithElement(element, handle);
 }
 /// <summary>
 /// Add a space to the wrapper, with associated level and extrusion data information.
 /// </summary>
 /// <param name="element">The element.</param>
 /// <param name="handle">The element handle.</param>
 /// <param name="levelInfo">The level information.</param>
 /// <param name="data">The extrusion creation data (can be null.)</param>
 /// <param name="relateToLevel">Relate to the level in the setter, or not.</param>
 public void AddSpace(Element element, IFCAnyHandle handle, IFCLevelInfo levelInfo, IFCExtrusionCreationData data, bool relateToLevel)
 {
    bool actuallyRelateToLevel = relateToLevel && (levelInfo != null);
    m_InternalWrapper.AddSpace(handle, levelInfo, data, actuallyRelateToLevel);
    if (levelInfo == null && relateToLevel)
       ExporterCacheManager.LevelInfoCache.OrphanedSpaces.Add(handle);
    RegisterHandleWithElement(element, handle);
 }
 /// <summary>
 /// Adds an annotation handle to associate with the IfcProduct in this wrapper.
 /// </summary>
 /// <param name="handle">The annotation handle.</param>
 /// <param name="levelInfo">The level information, can be null if relateToLevel is false.</param>
 /// <param name="relateToLevel">Whether the annotation is contained in a level.</param>
 public void AddAnnotation(IFCAnyHandle handle, IFCLevelInfo levelInfo, bool relateToLevel)
 {
     m_InternalWrapper.AddAnnotation(handle, levelInfo, relateToLevel);
 }
 /// <summary>
 /// Add a space to the wrapper, with associated level and extrusion data information.
 /// </summary>
 /// <param name="element">The element.</param>
 /// <param name="handle">The element handle.</param>
 /// <param name="levelInfo">The level information.</param>
 /// <param name="data">The extrusion creation data (can be null.)</param>
 /// <param name="relateToLevel">Relate to the level in the setter, or not.</param>
 public void AddSpace(Element element, IFCAnyHandle handle, IFCLevelInfo levelInfo, IFCExtrusionCreationData data, bool relateToLevel)
 {
     m_InternalWrapper.AddSpace(handle, levelInfo, data, relateToLevel);
     RegisterHandleWithElement(element, handle);
 }
Example #13
0
        /// <summary>
        /// Export one IFCGrid in one level.
        /// </summary>
        /// <param name="exporterIFC">The ExporterIFC object.</param>
        /// <param name="levelId">The level ID.</param>
        /// <param name="sameDirectionAxesU">The U axes of grids.</param>
        /// <param name="sameDirectionAxesV">The V axes of grids.</param>
        /// <param name="sameDirectionAxesW">The W axes of grids.</param>
        public static void ExportGrid(ExporterIFC exporterIFC, ElementId levelId, List <Grid> sameDirectionAxesU, List <Grid> sameDirectionAxesV, List <Grid> sameDirectionAxesW)
        {
            List <IFCAnyHandle> axesU           = null;
            List <IFCAnyHandle> axesV           = null;
            List <IFCAnyHandle> axesW           = null;
            List <IFCAnyHandle> representations = new List <IFCAnyHandle>();

            using (ProductWrapper productWrapper = ProductWrapper.Create(exporterIFC, true))
            {
                IFCFile ifcFile = exporterIFC.GetFile();
                using (IFCTransaction transaction = new IFCTransaction(ifcFile))
                {
                    GridRepresentationData gridRepresentationData = new GridRepresentationData();

                    axesU = CreateIFCGridAxisAndRepresentations(exporterIFC, productWrapper, sameDirectionAxesU, representations, gridRepresentationData);
                    axesV = CreateIFCGridAxisAndRepresentations(exporterIFC, productWrapper, sameDirectionAxesV, representations, gridRepresentationData);
                    if (sameDirectionAxesW != null)
                    {
                        axesW = CreateIFCGridAxisAndRepresentations(exporterIFC, productWrapper, sameDirectionAxesW, representations, gridRepresentationData);
                    }

                    IFCAnyHandle contextOfItemsFootPrint = exporterIFC.Get3DContextHandle("FootPrint");
                    string       identifierOpt           = "FootPrint";
                    string       representationTypeOpt   = "GeometricCurveSet";

                    int numGridsToExport = gridRepresentationData.m_Grids.Count;
                    if (numGridsToExport == 0)
                    {
                        return;
                    }

                    bool useIFCCADLayer = !string.IsNullOrWhiteSpace(gridRepresentationData.m_IFCCADLayer);

                    IFCAnyHandle shapeRepresentation = null;

                    HashSet <IFCAnyHandle> allCurves = new HashSet <IFCAnyHandle>();
                    for (int ii = 0; ii < numGridsToExport; ii++)
                    {
                        allCurves.UnionWith(gridRepresentationData.m_curveSets[ii]);
                    }

                    if (useIFCCADLayer)
                    {
                        shapeRepresentation = RepresentationUtil.CreateShapeRepresentation(exporterIFC, contextOfItemsFootPrint,
                                                                                           identifierOpt, representationTypeOpt, allCurves, gridRepresentationData.m_IFCCADLayer);
                    }
                    else
                    {
                        ElementId catId = CategoryUtil.GetSafeCategoryId(gridRepresentationData.m_Grids[0]);
                        shapeRepresentation = RepresentationUtil.CreateShapeRepresentation(exporterIFC, gridRepresentationData.m_Grids[0], catId,
                                                                                           contextOfItemsFootPrint, identifierOpt, representationTypeOpt, allCurves);
                    }
                    representations.Add(shapeRepresentation);

                    IFCAnyHandle productRep = IFCInstanceExporter.CreateProductDefinitionShape(ifcFile, null, null, representations);

                    IFCLevelInfo levelInfo = ExporterCacheManager.LevelInfoCache.GetLevelInfo(exporterIFC, levelId);

                    string gridGUID = GUIDUtil.CreateGUID();
                    // Get the first grid's override name, if cannot find it, use null.
                    string       gridName             = GetGridName(sameDirectionAxesU, sameDirectionAxesV, sameDirectionAxesW);
                    IFCAnyHandle ownerHistory         = exporterIFC.GetOwnerHistoryHandle();
                    IFCAnyHandle gridLevelHandle      = levelInfo.GetBuildingStorey();
                    IFCAnyHandle levelObjectPlacement = IFCAnyHandleUtil.GetObjectPlacement(gridLevelHandle);
                    double       elev               = levelInfo.Elevation;
                    double       elevation          = UnitUtil.ScaleLength(elev);
                    XYZ          orig               = new XYZ(0.0, 0.0, elevation);
                    IFCAnyHandle copyLevelPlacement = ExporterUtil.CopyLocalPlacement(ifcFile, levelObjectPlacement);
                    IFCAnyHandle ifcGrid            = IFCInstanceExporter.CreateGrid(ifcFile, gridGUID, ownerHistory, gridName, null, null, copyLevelPlacement, productRep, axesU, axesV, axesW);
                    productWrapper.AddElement(null, ifcGrid, levelInfo, null, true);

                    transaction.Commit();
                }
            }
        }
Example #14
0
        /// <summary>
        /// Creates a list of ranges to split an element.
        /// </summary>
        /// <remarks>
        /// We may need to split an element (e.g. column) into parts by level.
        /// </remarks>
        /// <param name="exporterIFC">
        /// The ExporterIFC object.
        /// </param>
        /// <param name="exportType">
        /// The export type.
        /// </param>
        /// <param name="element">
        /// The element.
        /// </param>
        /// <param name="levels">
        /// The levels to split the element.
        /// </param>
        /// <param name="ranges">
        /// The ranges to split the element.
        /// </param>
        public static void CreateSplitLevelRangesForElement(ExporterIFC exporterIFC, IFCExportType exportType, Element element,
                                                            out IList <ElementId> levels, out IList <IFCRange> ranges)
        {
            levels = new List <ElementId>();
            ranges = new List <IFCRange>();
            double extension = GetLevelExtension();

            if ((exportType == IFCExportType.ExportColumnType || exportType == IFCExportType.ExportWall) && (ExporterCacheManager.ExportOptionsCache.WallAndColumnSplitting))
            {
                BoundingBoxXYZ boundingBox = element.get_BoundingBox(null);
                {
                    IFCRange zSpan = new IFCRange(boundingBox.Min.Z, boundingBox.Max.Z);
                    if (zSpan.Start < zSpan.End)
                    {
                        bool      firstLevel      = true;
                        ElementId skipToNextLevel = ElementId.InvalidElementId;

                        // If the base level of the element is set, we will start "looking" at that level.  Anything below the base level will be included with the base level.
                        // We will only do this if the base level is a building story.
                        ElementId firstLevelId    = GetBaseLevelIdForElement(element);
                        bool      foundFirstLevel = (firstLevelId == ElementId.InvalidElementId);

                        List <ElementId> levelIds = ExporterCacheManager.LevelInfoCache.LevelsByElevation;
                        foreach (ElementId levelId in levelIds)
                        {
                            if (!foundFirstLevel)
                            {
                                if (levelId != firstLevelId)
                                {
                                    continue;
                                }
                                else
                                {
                                    foundFirstLevel = true;
                                }
                            }

                            if (skipToNextLevel != ElementId.InvalidElementId && levelId != skipToNextLevel)
                            {
                                continue;
                            }

                            IFCLevelInfo levelInfo = ExporterCacheManager.LevelInfoCache.GetLevelInfo(exporterIFC, levelId);
                            if (levelInfo == null)
                            {
                                continue;
                            }

                            // endBelowLevel
                            if (zSpan.End < levelInfo.Elevation + extension)
                            {
                                continue;
                            }

                            // To calculate the distance to the next level, we check to see if the Level UpToLevel built-in parameter
                            // is set.  If so, we calculate the distance by getting the elevation of the UpToLevel level minus the
                            // current elevation, and use it if it is greater than 0.  If it is not greater than 0, or the built-in
                            // parameter is not set, we use DistanceToNextLevel.
                            double levelHeight = ExporterCacheManager.LevelInfoCache.FindHeight(levelId);
                            if (levelHeight < 0.0)
                            {
                                levelHeight = calculateDistanceToNextLevel(element.Document, levelId, levelInfo);
                            }
                            skipToNextLevel = ExporterCacheManager.LevelInfoCache.FindNextLevel(levelId);

                            // startAboveLevel
                            if ((!MathUtil.IsAlmostZero(levelHeight)) &&
                                (zSpan.Start > levelInfo.Elevation + levelHeight - extension))
                            {
                                continue;
                            }

                            bool startBelowLevel = !firstLevel && (zSpan.Start < levelInfo.Elevation - extension);
                            bool endAboveLevel   = ((!MathUtil.IsAlmostZero(levelHeight)) &&
                                                    (zSpan.End > levelInfo.Elevation + levelHeight + extension));
                            if (!startBelowLevel && !endAboveLevel)
                            {
                                break;
                            }

                            IFCRange currentSpan = new IFCRange(
                                startBelowLevel ? levelInfo.Elevation : zSpan.Start,
                                endAboveLevel ? (levelInfo.Elevation + levelHeight) : zSpan.End);
                            ranges.Add(currentSpan);
                            levels.Add(levelId);

                            firstLevel = false;
                        }
                    }
                }
            }
        }
Example #15
0
        /// <summary>
        /// Creates a list of ranges to split an element.
        /// </summary>
        /// <remarks>
        /// We may need to split an element (e.g. column) into parts by level.
        /// </remarks>
        /// <param name="exporterIFC">The ExporterIFC object. </param>
        /// <param name="exportType">The export type. </param>
        /// <param name="element">The element. </param>
        /// <param name="levels">The levels to split the element.</param>
        /// <param name="ranges">The ranges to split the element. These will be non-overlapping.</param>
        public static void CreateSplitLevelRangesForElement(ExporterIFC exporterIFC, IFCExportType exportType, Element element,
                                                            out IList <ElementId> levels, out IList <IFCRange> ranges)
        {
            levels = new List <ElementId>();
            ranges = new List <IFCRange>();

            if (!ExporterCacheManager.ExportOptionsCache.WallAndColumnSplitting)
            {
                return;
            }

            double extension = GetLevelExtension();

            bool splitByLevel = (exportType == IFCExportType.IfcColumnType || exportType == IFCExportType.IfcWall) || (exportType == IFCExportType.IfcDuctSegmentType);

            if (!splitByLevel)
            {
                return;
            }

            BoundingBoxXYZ boundingBox = element.get_BoundingBox(null);

            if (boundingBox == null)
            {
                return;
            }

            {
                IFCRange zSpan = new IFCRange(boundingBox.Min.Z, boundingBox.Max.Z);
                if (zSpan.Start < zSpan.End)
                {
                    bool      firstLevel      = true;
                    ElementId skipToNextLevel = ElementId.InvalidElementId;

                    // If the base level of the element is set, we will start "looking" at that level.  Anything below the base level will be included with the base level.
                    // We will only do this if the base level is a building story.
                    ElementId firstLevelId    = GetBaseLevelIdForElement(element);
                    bool      foundFirstLevel = (firstLevelId == ElementId.InvalidElementId);

                    IList <ElementId> levelIds = ExporterCacheManager.LevelInfoCache.BuildingStoreysByElevation;
                    foreach (ElementId levelId in levelIds)
                    {
                        if (!foundFirstLevel)
                        {
                            if (levelId != firstLevelId)
                            {
                                continue;
                            }
                            else
                            {
                                foundFirstLevel = true;
                            }
                        }

                        if (skipToNextLevel != ElementId.InvalidElementId && levelId != skipToNextLevel)
                        {
                            continue;
                        }

                        IFCLevelInfo levelInfo = ExporterCacheManager.LevelInfoCache.GetLevelInfo(exporterIFC, levelId);
                        if (levelInfo == null)
                        {
                            continue;
                        }

                        // endBelowLevel
                        if (zSpan.End < levelInfo.Elevation + extension)
                        {
                            continue;
                        }

                        // To calculate the distance to the next level, we check to see if the Level UpToLevel built-in parameter
                        // is set.  If so, we calculate the distance by getting the elevation of the UpToLevel level minus the
                        // current elevation, and use it if it is greater than 0.  If it is not greater than 0, or the built-in
                        // parameter is not set, we use DistanceToNextLevel.
                        double levelHeight = ExporterCacheManager.LevelInfoCache.FindHeight(levelId);
                        if (levelHeight < 0.0)
                        {
                            levelHeight = CalculateDistanceToNextLevel(element.Document, levelId, levelInfo);
                        }
                        skipToNextLevel = ExporterCacheManager.LevelInfoCache.FindNextLevel(levelId);

                        // startAboveLevel
                        if ((!MathUtil.IsAlmostZero(levelHeight)) &&
                            (zSpan.Start > levelInfo.Elevation + levelHeight - extension))
                        {
                            continue;
                        }

                        bool startBelowLevel = !firstLevel && (zSpan.Start < levelInfo.Elevation - extension);
                        bool endAboveLevel   = ((!MathUtil.IsAlmostZero(levelHeight)) &&
                                                (zSpan.End > levelInfo.Elevation + levelHeight + extension));
                        if (!startBelowLevel && !endAboveLevel)
                        {
                            break;
                        }

                        IFCRange currentSpan = new IFCRange(
                            startBelowLevel ? levelInfo.Elevation : zSpan.Start,
                            endAboveLevel ? (levelInfo.Elevation + levelHeight) : zSpan.End);

                        // We want our ranges to be non-overlapping.  As such, we'll modify the start parameter
                        // to be at least as large as the previous end parameter (if any).  If this makes the
                        // range invalid, we won't add it.
                        if (ranges.Count > 0)
                        {
                            IFCRange lastSpan = ranges.Last();
                            if (lastSpan.End > currentSpan.End - MathUtil.Eps())
                            {
                                continue;
                            }

                            currentSpan.Start = Math.Max(currentSpan.Start, lastSpan.End);
                        }

                        ranges.Add(currentSpan);
                        levels.Add(levelId);

                        firstLevel = false;
                    }
                }
            }
        }
Example #16
0
 /// <summary>
 /// The constructor for the class.
 /// </summary>
 /// <param name="rebarElement">The element that created the rebar.</param>
 /// <param name="elementHandle">The associated IFC element handle.</param>
 /// <param name="levelInfo">The information for the associated level.</param>
 public DelayedProductWrapper(Element rebarElement, IFCAnyHandle elementHandle, IFCLevelInfo levelInfo)
 {
     RebarElement  = rebarElement;
     ElementHandle = elementHandle;
     LevelInfo     = levelInfo;
 }
Example #17
0
 /// <summary>
 /// Adds an annotation handle to associate with the IfcProduct in this wrapper.
 /// </summary>
 /// <param name="handle">The annotation handle.</param>
 /// <param name="levelInfo">The level information, can be null if relateToLevel is false.</param>
 /// <param name="relateToLevel">Whether the annotation is contained in a level.</param>
 public void AddAnnotation(IFCAnyHandle handle, IFCLevelInfo levelInfo, bool relateToLevel)
 {
     // The internal AddAnnotation takes an optional levelInfo, so we don't need to do a levelInfo null check here.
     m_InternalWrapper.AddAnnotation(handle, levelInfo, relateToLevel);
 }
Example #18
0
        /// <summary>
        /// Export one IFCGrid in one level.
        /// </summary>
        /// <param name="exporterIFC">The ExporterIFC object.</param>
        /// <param name="levelId">The level ID.</param>
        /// <param name="sameDirectionAxesU">The U axes of grids.</param>
        /// <param name="sameDirectionAxesV">The V axes of grids.</param>
        /// <param name="sameDirectionAxesW">The W axes of grids.</param>
        public static void ExportGrid(ExporterIFC exporterIFC, ElementId levelId, string gridName, List <Grid> sameDirectionAxesU, List <Grid> sameDirectionAxesV, List <Grid> sameDirectionAxesW)
        {
            List <IFCAnyHandle> axesU           = null;
            List <IFCAnyHandle> axesV           = null;
            List <IFCAnyHandle> axesW           = null;
            List <IFCAnyHandle> representations = new List <IFCAnyHandle>();

            using (ProductWrapper productWrapper = ProductWrapper.Create(exporterIFC, true))
            {
                IFCFile ifcFile = exporterIFC.GetFile();
                using (IFCTransaction transaction = new IFCTransaction(ifcFile))
                {
                    GridRepresentationData gridRepresentationData = new GridRepresentationData();

                    axesU = CreateIFCGridAxisAndRepresentations(exporterIFC, productWrapper, sameDirectionAxesU, representations, gridRepresentationData);
                    axesV = CreateIFCGridAxisAndRepresentations(exporterIFC, productWrapper, sameDirectionAxesV, representations, gridRepresentationData);
                    if (sameDirectionAxesW != null)
                    {
                        axesW = CreateIFCGridAxisAndRepresentations(exporterIFC, productWrapper, sameDirectionAxesW, representations, gridRepresentationData);
                    }

                    IFCAnyHandle contextOfItemsFootPrint = exporterIFC.Get3DContextHandle("FootPrint");
                    string       identifierOpt           = "FootPrint";
                    string       representationTypeOpt   = "GeometricCurveSet";

                    int numGridsToExport = gridRepresentationData.m_Grids.Count;
                    if (numGridsToExport == 0)
                    {
                        return;
                    }

                    bool useIFCCADLayer = !string.IsNullOrWhiteSpace(gridRepresentationData.m_IFCCADLayer);

                    IFCAnyHandle shapeRepresentation = null;

                    HashSet <IFCAnyHandle> allCurves = new HashSet <IFCAnyHandle>();
                    for (int ii = 0; ii < numGridsToExport; ii++)
                    {
                        allCurves.UnionWith(gridRepresentationData.m_curveSets[ii]);
                    }

                    if (useIFCCADLayer)
                    {
                        shapeRepresentation = RepresentationUtil.CreateShapeRepresentation(exporterIFC, contextOfItemsFootPrint,
                                                                                           identifierOpt, representationTypeOpt, allCurves, gridRepresentationData.m_IFCCADLayer);
                    }
                    else
                    {
                        ElementId catId = CategoryUtil.GetSafeCategoryId(gridRepresentationData.m_Grids[0]);
                        shapeRepresentation = RepresentationUtil.CreateShapeRepresentation(exporterIFC, gridRepresentationData.m_Grids[0], catId,
                                                                                           contextOfItemsFootPrint, identifierOpt, representationTypeOpt, allCurves);
                    }
                    representations.Add(shapeRepresentation);

                    IFCAnyHandle productRep = IFCInstanceExporter.CreateProductDefinitionShape(ifcFile, null, null, representations);

                    // We will associate the grid with its level, unless there are no levels in the file, in which case we'll associate it with the building.
                    IFCLevelInfo levelInfo    = ExporterCacheManager.LevelInfoCache.GetLevelInfo(exporterIFC, levelId);
                    bool         useLevelInfo = (levelInfo != null);

                    string gridGUID = GUIDUtil.CreateGUID();

                    IFCAnyHandle ownerHistory         = ExporterCacheManager.OwnerHistoryHandle;
                    IFCAnyHandle gridLevelHandle      = useLevelInfo ? levelInfo.GetBuildingStorey() : ExporterCacheManager.BuildingHandle;
                    IFCAnyHandle levelObjectPlacement = (gridLevelHandle != null) ? IFCAnyHandleUtil.GetObjectPlacement(gridLevelHandle) : null;
                    IFCAnyHandle copyLevelPlacement   = (levelObjectPlacement != null) ? ExporterUtil.CopyLocalPlacement(ifcFile, levelObjectPlacement) : null;
                    IFCAnyHandle ifcGrid = IFCInstanceExporter.CreateGrid(exporterIFC, gridGUID, ownerHistory, gridName, copyLevelPlacement, productRep, axesU, axesV, axesW);

                    productWrapper.AddElement(null, ifcGrid, levelInfo, null, true, null);

                    transaction.Commit();
                }
            }
        }
Example #19
0
 /// <summary>
 /// Add a space to the wrapper, with associated level and extrusion data information.
 /// </summary>
 /// <param name="element">The element.</param>
 /// <param name="handle">The element handle.</param>
 /// <param name="levelInfo">The level information.</param>
 /// <param name="data">The extrusion creation data (can be null.)</param>
 /// <param name="relateToLevel">Relate to the level in the setter, or not.</param>
 public void AddSpace(Element element, IFCAnyHandle handle, IFCLevelInfo levelInfo, IFCExtrusionCreationData data, bool relateToLevel)
 {
     m_InternalWrapper.AddSpace(handle, levelInfo, data, relateToLevel);
     RegisterHandleWithElement(element, handle);
 }
Example #20
0
 /// <summary>
 /// Adds an annotation handle to associate with the IfcProduct in this wrapper.
 /// </summary>
 /// <param name="handle">The annotation handle.</param>
 /// <param name="levelInfo">The level information, can be null if relateToLevel is false.</param>
 /// <param name="relateToLevel">Whether the annotation is contained in a level.</param>
 public void AddAnnotation(IFCAnyHandle handle, IFCLevelInfo levelInfo, bool relateToLevel)
 {
     m_InternalWrapper.AddAnnotation(handle, levelInfo, relateToLevel);
 }
Example #21
0
 /// <summary>
 /// Adds an IFCLevelInfo to the LevelsByElevation list, also updating the native cache item.
 /// </summary>
 /// <param name="exporterIFC">
 /// The exporter data object.
 /// </param>
 /// <param name="levelId">
 /// The level ElementId.
 /// </param>
 /// <param name="info">
 /// The IFCLevelInfo.
 /// </param>
 public void AddLevelInfo(ExporterIFC exporterIFC, ElementId levelId, IFCLevelInfo info)
 {
     LevelsByElevation.Add(levelId);
     exporterIFC.AddBuildingStorey(levelId, info);
 }
        /// <summary>
        /// Get the height of a spatial element.
        /// </summary>
        /// <param name="spatialElement">
        /// The spatial element.
        /// </param>
        /// <param name="scale">
        /// The scale value.
        /// </param>
        /// <param name="levelInfo">
        /// The level info.
        /// </param>
        /// <returns>
        /// The height.
        /// </returns>
        static double GetHeight(SpatialElement spatialElement, double scale, IFCLevelInfo levelInfo)
        {
            Document document = spatialElement.Document;

            double roomHeight = 0.0;
            double bottomOffset = 0.0;

            ElementId bottomLevelId = spatialElement.Level.Id;

            Parameter paramTopLevelId = spatialElement.get_Parameter(BuiltInParameter.ROOM_UPPER_LEVEL);
            ElementId topLevelId = paramTopLevelId != null ? paramTopLevelId.AsElementId() : ElementId.InvalidElementId;

            Parameter paramTopOffset = spatialElement.get_Parameter(BuiltInParameter.ROOM_UPPER_OFFSET);
            double topOffset = paramTopOffset != null ? paramTopOffset.AsDouble() : 0.0;

            Parameter paramBottomOffset = spatialElement.get_Parameter(BuiltInParameter.ROOM_LOWER_OFFSET);
            bottomOffset = paramBottomOffset != null ? paramBottomOffset.AsDouble() : 0.0;

            Level bottomLevel = document.get_Element(bottomLevelId) as Level;
            Level topLevel =
               (bottomLevelId == topLevelId) ? bottomLevel : document.get_Element(topLevelId) as Level;

            if (bottomLevel != null && topLevel != null)
            {
                roomHeight = (topLevel.Elevation - bottomLevel.Elevation) + (topOffset - bottomOffset);
                roomHeight *= scale;
            }

            if (MathUtil.IsAlmostZero(roomHeight))
            {
                roomHeight = levelInfo.DistanceToNextLevel * scale;
            }

            // For area spaces, we assign a dummy height (1'), as we are not allowed to export IfcSpaces without a volumetric representation.
            if (MathUtil.IsAlmostZero(roomHeight) && spatialElement is Area)
            {
                roomHeight = 1.0;
            }

            return roomHeight;
        }
        /// <summary>
        /// Attempt to determine the local placement of the element based on the element type and initial input.
        /// </summary>
        /// <param name="exporterIFC">The ExporterIFC class.</param>
        /// <param name="elem">The element being exported.</param>
        /// <param name="familyTrf">The optional family transform.</param>
        /// <param name="orientationTrf">The optional orientation of the element based on IFC standards or agreements.</param>
        /// <param name="overrideLevelId">The optional level to place the element, to be used instead of heuristics.</param>
        private void commonInit(ExporterIFC exporterIFC, Element elem, Transform familyTrf, Transform orientationTrf, ElementId overrideLevelId)
        {
            ExporterIFC = exporterIFC;

            // Convert null value to InvalidElementId.
            if (overrideLevelId == null)
            {
                overrideLevelId = ElementId.InvalidElementId;
            }

            Document  doc        = elem.Document;
            Element   hostElem   = elem;
            ElementId elemId     = elem.Id;
            ElementId newLevelId = overrideLevelId;

            bool useOverrideOrigin = false;
            XYZ  overrideOrigin    = XYZ.Zero;

            IDictionary <ElementId, IFCLevelInfo> levelInfos = exporterIFC.GetLevelInfos();

            if (overrideLevelId == ElementId.InvalidElementId)
            {
                if (familyTrf == null)
                {
                    // Override for CurveElems -- base level calculation on origin of sketch Plane.
                    if (elem is CurveElement)
                    {
                        SketchPlane sketchPlane = (elem as CurveElement).SketchPlane;
                        if (sketchPlane != null)
                        {
                            useOverrideOrigin = true;
                            overrideOrigin    = sketchPlane.GetPlane().Origin;
                        }
                    }
                    else
                    {
                        ElementId hostElemId = ElementId.InvalidElementId;
                        // a bit of a hack.  If we have a railing, we want it to have the same level base as its host Stair (because of
                        // the way the stairs place railings and stair flights together).
                        if (elem is Railing)
                        {
                            hostElemId = (elem as Railing).HostId;
                        }
                        else if (elem.Category.Id.IntegerValue == (int)BuiltInCategory.OST_Assemblies)
                        {
                            hostElemId = elem.AssemblyInstanceId;
                        }

                        if (hostElemId != ElementId.InvalidElementId)
                        {
                            hostElem = doc.GetElement(hostElemId);
                        }

                        newLevelId = hostElem != null ? hostElem.LevelId : ElementId.InvalidElementId;

                        if (newLevelId == ElementId.InvalidElementId)
                        {
                            ExporterIFCUtils.GetLevelIdByHeight(exporterIFC, hostElem);
                        }
                    }
                }

                // todo: store.
                double    bottomHeight  = double.MaxValue;
                ElementId bottomLevelId = ElementId.InvalidElementId;
                if ((newLevelId == ElementId.InvalidElementId) || orientationTrf != null)
                {
                    // if we have a trf, it might geometrically push the instance to a new level.  Check that case.
                    // actually, we should ALWAYS check the bbox vs the settings
                    newLevelId = ElementId.InvalidElementId;
                    XYZ  originToUse   = XYZ.Zero;
                    bool originIsValid = useOverrideOrigin;

                    if (useOverrideOrigin)
                    {
                        originToUse = overrideOrigin;
                    }
                    else
                    {
                        BoundingBoxXYZ bbox = elem.get_BoundingBox(null);
                        if (bbox != null)
                        {
                            originToUse   = bbox.Min;
                            originIsValid = true;
                        }
                        else if (hostElem.Id != elemId)
                        {
                            bbox = hostElem.get_BoundingBox(null);
                            if (bbox != null)
                            {
                                originToUse   = bbox.Min;
                                originIsValid = true;
                            }
                        }
                    }


                    // The original heuristic here was that the origin determined the level containment based on exact location:
                    // if the Z of the origin was higher than the current level but lower than the next level, it was contained
                    // on that level.
                    // However, in some places (e.g. Germany), the containment is thought to start just below the level, because floors
                    // are placed before the level, not above.  So we have made a small modification so that anything within
                    // 10cm of the 'next' level is on that level.

                    double leveExtension = 10.0 / (12.0 * 2.54);
                    foreach (KeyValuePair <ElementId, IFCLevelInfo> levelInfoPair in levelInfos)
                    {
                        // the cache contains levels from all the exported documents
                        // if the export is performed for a linked document, filter the levels that are not from this document
                        if (ExporterCacheManager.ExportOptionsCache.ExportingLink)
                        {
                            Element levelElem = doc.GetElement(levelInfoPair.Key);
                            if (levelElem == null || !(levelElem is Level))
                            {
                                continue;
                            }
                        }

                        IFCLevelInfo levelInfo   = levelInfoPair.Value;
                        double       startHeight = levelInfo.Elevation - leveExtension;
                        double       height      = levelInfo.DistanceToNextLevel;
                        bool         useHeight   = !MathUtil.IsAlmostZero(height);
                        double       endHeight   = startHeight + height;

                        if (originIsValid && ((originToUse[2] > (startHeight - MathUtil.Eps())) && (!useHeight || originToUse[2] < (endHeight - MathUtil.Eps()))))
                        {
                            newLevelId = levelInfoPair.Key;
                        }

                        if (startHeight < (bottomHeight + MathUtil.Eps()))
                        {
                            bottomLevelId = levelInfoPair.Key;
                            bottomHeight  = startHeight;
                        }
                    }
                }

                if (newLevelId == ElementId.InvalidElementId)
                {
                    newLevelId = bottomLevelId;
                }
            }

            LevelInfo = exporterIFC.GetLevelInfo(newLevelId);
            if (LevelInfo == null)
            {
                foreach (KeyValuePair <ElementId, IFCLevelInfo> levelInfoPair in levelInfos)
                {
                    // the cache contains levels from all the exported documents
                    // if the export is performed for a linked document, filter the levels that are not from this document
                    if (ExporterCacheManager.ExportOptionsCache.ExportingLink)
                    {
                        Element levelElem = doc.GetElement(levelInfoPair.Key);
                        if (levelElem == null || !(levelElem is Level))
                        {
                            continue;
                        }
                    }
                    LevelInfo = levelInfoPair.Value;
                    break;
                }
                //LevelInfo = levelInfos.Values.First<IFCLevelInfo>();
            }

            double       elevation      = (LevelInfo != null) ? LevelInfo.Elevation : 0.0;
            IFCAnyHandle levelPlacement = (LevelInfo != null) ? LevelInfo.GetLocalPlacement() : null;

            IFCFile file = exporterIFC.GetFile();

            Transform trf = Transform.Identity;

            if (familyTrf != null)
            {
                XYZ origin, xDir, yDir, zDir;

                xDir = familyTrf.BasisX; yDir = familyTrf.BasisY; zDir = familyTrf.BasisZ;

                Transform origOffsetTrf  = Transform.Identity;
                XYZ       negLevelOrigin = new XYZ(0, 0, -elevation);
                origOffsetTrf.Origin = negLevelOrigin;

                Transform newTrf = origOffsetTrf * familyTrf;

                origin = newTrf.Origin;

                trf.BasisX = xDir; trf.BasisY = yDir; trf.BasisZ = zDir;
                trf        = trf.Inverse;

                origin         = UnitUtil.ScaleLength(origin);
                LocalPlacement = ExporterUtil.CreateLocalPlacement(file, levelPlacement, origin, zDir, xDir);
            }
            else if (orientationTrf != null)
            {
                XYZ origin, xDir, yDir, zDir;

                xDir = orientationTrf.BasisX; yDir = orientationTrf.BasisY; zDir = orientationTrf.BasisZ; origin = orientationTrf.Origin;

                XYZ levelOrigin = new XYZ(0, 0, elevation);
                origin = origin - levelOrigin;

                trf.BasisX = xDir; trf.BasisY = yDir; trf.BasisZ = zDir; trf.Origin = origin;
                trf        = trf.Inverse;

                origin         = UnitUtil.ScaleLength(origin);
                LocalPlacement = ExporterUtil.CreateLocalPlacement(file, levelPlacement, origin, zDir, xDir);
            }
            else
            {
                LocalPlacement = ExporterUtil.CreateLocalPlacement(file, levelPlacement, null, null, null);
            }

            Transform origOffsetTrf2  = Transform.Identity;
            XYZ       negLevelOrigin2 = new XYZ(0, 0, -elevation);

            origOffsetTrf2.Origin = negLevelOrigin2;
            Transform newTrf2 = trf * origOffsetTrf2;

            ExporterIFC.PushTransform(newTrf2);
            Offset  = elevation;
            LevelId = newLevelId;
        }
      /// <summary>
      /// Attempt to determine the local placement of the element based on the element type and initial input.
      /// </summary>
      /// <param name="exporterIFC">The ExporterIFC class.</param>
      /// <param name="elem">The element being exported.</param>
      /// <param name="familyTrf">The optional family transform.</param>
      /// <param name="orientationTrf">The optional orientation of the element based on IFC standards or agreements.</param>
      /// <param name="overrideLevelId">The optional level to place the element, to be used instead of heuristics.</param>
      private void commonInit(ExporterIFC exporterIFC, Element elem, Transform familyTrf, Transform orientationTrf, ElementId overrideLevelId)
      {
         ExporterIFC = exporterIFC;

         // Convert null value to InvalidElementId.
         if (overrideLevelId == null)
            overrideLevelId = ElementId.InvalidElementId;

         Document doc = elem.Document;
         Element hostElem = elem;
         ElementId elemId = elem.Id;
         ElementId newLevelId = overrideLevelId;

         bool useOverrideOrigin = false;
         XYZ overrideOrigin = XYZ.Zero;

         IDictionary<ElementId, IFCLevelInfo> levelInfos = exporterIFC.GetLevelInfos();

         if (overrideLevelId == ElementId.InvalidElementId)
         {
            if (familyTrf == null)
            {
               // Override for CurveElems -- base level calculation on origin of sketch Plane.
               if (elem is CurveElement)
               {
                  SketchPlane sketchPlane = (elem as CurveElement).SketchPlane;
                  if (sketchPlane != null)
                  {
                     useOverrideOrigin = true;
                     overrideOrigin = sketchPlane.GetPlane().Origin;
                  }
               }
               else
               {
                  ElementId hostElemId = ElementId.InvalidElementId;
                  // a bit of a hack.  If we have a railing, we want it to have the same level base as its host Stair (because of
                  // the way the stairs place railings and stair flights together).
                  if (elem is Railing)
                  {
                     hostElemId = (elem as Railing).HostId;
                  }
                  else if (elem.Category.Id.IntegerValue == (int)BuiltInCategory.OST_Assemblies)
                  {
                     hostElemId = elem.AssemblyInstanceId;
                  }

                  if (hostElemId != ElementId.InvalidElementId)
                  {
                     hostElem = doc.GetElement(hostElemId);
                  }

                  newLevelId = hostElem != null ? hostElem.LevelId : ElementId.InvalidElementId;

                  if (newLevelId == ElementId.InvalidElementId)
                  {
                     ExporterIFCUtils.GetLevelIdByHeight(exporterIFC, hostElem);
                  }
               }
            }

            // todo: store.
            double bottomHeight = double.MaxValue;
            ElementId bottomLevelId = ElementId.InvalidElementId;
            if ((newLevelId == ElementId.InvalidElementId) || orientationTrf != null)
            {
               // if we have a trf, it might geometrically push the instance to a new level.  Check that case.
               // actually, we should ALWAYS check the bbox vs the settings
               newLevelId = ElementId.InvalidElementId;
               XYZ originToUse = XYZ.Zero;
               bool originIsValid = useOverrideOrigin;

               if (useOverrideOrigin)
               {
                  originToUse = overrideOrigin;
               }
               else
               {
                  BoundingBoxXYZ bbox = elem.get_BoundingBox(null);
                  if (bbox != null)
                  {
                     originToUse = bbox.Min;
                     originIsValid = true;
                  }
                  else if (hostElem.Id != elemId)
                  {
                     bbox = hostElem.get_BoundingBox(null);
                     if (bbox != null)
                     {
                        originToUse = bbox.Min;
                        originIsValid = true;
                     }
                  }
               }


               // The original heuristic here was that the origin determined the level containment based on exact location:
               // if the Z of the origin was higher than the current level but lower than the next level, it was contained
               // on that level.
               // However, in some places (e.g. Germany), the containment is thought to start just below the level, because floors
               // are placed before the level, not above.  So we have made a small modification so that anything within
               // 10cm of the 'next' level is on that level.

               double leveExtension = 10.0 / (12.0 * 2.54);
               foreach (KeyValuePair<ElementId, IFCLevelInfo> levelInfoPair in levelInfos)
               {
                  // the cache contains levels from all the exported documents
                  // if the export is performed for a linked document, filter the levels that are not from this document
                  if (ExporterCacheManager.ExportOptionsCache.ExportingLink)
                  {
                     Element levelElem = doc.GetElement(levelInfoPair.Key);
                     if (levelElem == null || !(levelElem is Level))
                        continue;
                  }

                  IFCLevelInfo levelInfo = levelInfoPair.Value;
                  double startHeight = levelInfo.Elevation - leveExtension;
                  double height = levelInfo.DistanceToNextLevel;
                  bool useHeight = !MathUtil.IsAlmostZero(height);
                  double endHeight = startHeight + height;

                  if (originIsValid && ((originToUse[2] > (startHeight - MathUtil.Eps())) && (!useHeight || originToUse[2] < (endHeight - MathUtil.Eps()))))
                  {
                     newLevelId = levelInfoPair.Key;
                  }

                  if (startHeight < (bottomHeight + MathUtil.Eps()))
                  {
                     bottomLevelId = levelInfoPair.Key;
                     bottomHeight = startHeight;
                  }
               }
            }

            if (newLevelId == ElementId.InvalidElementId)
               newLevelId = bottomLevelId;
         }

         LevelInfo = exporterIFC.GetLevelInfo(newLevelId);
         if (LevelInfo == null)
         {
            foreach (KeyValuePair<ElementId, IFCLevelInfo> levelInfoPair in levelInfos)
            {
               // the cache contains levels from all the exported documents
               // if the export is performed for a linked document, filter the levels that are not from this document
               if (ExporterCacheManager.ExportOptionsCache.ExportingLink)
               {
                  Element levelElem = doc.GetElement(levelInfoPair.Key);
                  if (levelElem == null || !(levelElem is Level))
                     continue;
               }
               LevelInfo = levelInfoPair.Value;
               break;
            }
            //LevelInfo = levelInfos.Values.First<IFCLevelInfo>();
         }

         double elevation = (LevelInfo != null) ? LevelInfo.Elevation : 0.0;
         IFCAnyHandle levelPlacement = (LevelInfo != null) ? LevelInfo.GetLocalPlacement() : null;

         IFCFile file = exporterIFC.GetFile();

         Transform trf = Transform.Identity;

         if (familyTrf != null)
         {
            XYZ origin, xDir, yDir, zDir;

            xDir = familyTrf.BasisX; yDir = familyTrf.BasisY; zDir = familyTrf.BasisZ;

            Transform origOffsetTrf = Transform.Identity;
            XYZ negLevelOrigin = new XYZ(0, 0, -elevation);
            origOffsetTrf.Origin = negLevelOrigin;

            Transform newTrf = origOffsetTrf * familyTrf;

            origin = newTrf.Origin;

            trf.BasisX = xDir; trf.BasisY = yDir; trf.BasisZ = zDir;
            trf = trf.Inverse;

            origin = UnitUtil.ScaleLength(origin);
            LocalPlacement = ExporterUtil.CreateLocalPlacement(file, levelPlacement, origin, zDir, xDir);
         }
         else if (orientationTrf != null)
         {
            XYZ origin, xDir, yDir, zDir;

            xDir = orientationTrf.BasisX; yDir = orientationTrf.BasisY; zDir = orientationTrf.BasisZ; origin = orientationTrf.Origin;

            XYZ levelOrigin = new XYZ(0, 0, elevation);
            origin = origin - levelOrigin;

            trf.BasisX = xDir; trf.BasisY = yDir; trf.BasisZ = zDir; trf.Origin = origin;
            trf = trf.Inverse;

            origin = UnitUtil.ScaleLength(origin);
            LocalPlacement = ExporterUtil.CreateLocalPlacement(file, levelPlacement, origin, zDir, xDir);
         }
         else
         {
            LocalPlacement = ExporterUtil.CreateLocalPlacement(file, levelPlacement, null, null, null);
         }

         Transform origOffsetTrf2 = Transform.Identity;
         XYZ negLevelOrigin2 = new XYZ(0, 0, -elevation);
         origOffsetTrf2.Origin = negLevelOrigin2;
         Transform newTrf2 = trf * origOffsetTrf2;

         ExporterIFC.PushTransform(newTrf2);
         Offset = elevation;
         LevelId = newLevelId;
      }
Example #25
0
        /// <summary>
        /// Split associated parts when host element is split by level.
        /// </summary>
        /// <param name="exporterIFC">The ExporterIFC object.</param>
        /// <param name="hostElement">The host element havign associtaed parts.</param>
        /// <param name="associatedPartsList">The list of associtated parts.</param>
        private static void SplitParts(ExporterIFC exporterIFC, Element hostElement, List <ElementId> associatedPartsList)
        {
            string            ifcEnumType;
            IFCExportInfoPair exportType = ExporterUtil.GetExportType(exporterIFC, hostElement, out ifcEnumType);

            // Split the host to find the orphan parts.
            IList <ElementId> orphanLevels = new List <ElementId>();
            IList <ElementId> hostLevels   = new List <ElementId>();
            IList <IFCRange>  hostRanges   = new List <IFCRange>();

            LevelUtil.CreateSplitLevelRangesForElement(exporterIFC, exportType, hostElement, out hostLevels, out hostRanges);
            orphanLevels = hostLevels;

            // Split each Parts
            IList <ElementId> levels = new List <ElementId>();
            IList <IFCRange>  ranges = new List <IFCRange>();
            // Dictionary to storage the level and its parts.
            Dictionary <ElementId, List <KeyValuePair <Part, IFCRange> > > levelParts = new Dictionary <ElementId, List <KeyValuePair <Part, IFCRange> > >();

            foreach (ElementId partId in associatedPartsList)
            {
                Part part = hostElement.Document.GetElement(partId) as Part;
                LevelUtil.CreateSplitLevelRangesForElement(exporterIFC, exportType, part, out levels, out ranges);

                // if the parts are above top level, associate them with nearest bottom level.
                if (ranges.Count == 0)
                {
                    ElementId bottomLevelId = FindPartSplitLevel(exporterIFC, part);

                    if (bottomLevelId == ElementId.InvalidElementId)
                    {
                        bottomLevelId = part.LevelId;
                    }

                    if (!levelParts.ContainsKey(bottomLevelId))
                    {
                        levelParts.Add(bottomLevelId, new List <KeyValuePair <Part, IFCRange> >());
                    }

                    KeyValuePair <Part, IFCRange> splitPartRange = new KeyValuePair <Part, IFCRange>(part, null);
                    levelParts[bottomLevelId].Add(splitPartRange);

                    continue;
                }

                // The parts split by levels are stored in dictionary.
                for (int ii = 0; ii < ranges.Count; ii++)
                {
                    if (!levelParts.ContainsKey(levels[ii]))
                    {
                        levelParts.Add(levels[ii], new List <KeyValuePair <Part, IFCRange> >());
                    }

                    KeyValuePair <Part, IFCRange> splitPartRange = new KeyValuePair <Part, IFCRange>(part, ranges[ii]);
                    levelParts[levels[ii]].Add(splitPartRange);
                }

                if (levels.Count > hostLevels.Count)
                {
                    orphanLevels = orphanLevels.Union <ElementId>(levels).ToList();
                }
            }

            ExporterCacheManager.HostPartsCache.Register(hostElement.Id, levelParts);

            // The levels of orphan part.
            orphanLevels = orphanLevels.Where(number => !hostLevels.Contains(number)).ToList();
            List <KeyValuePair <ElementId, IFCRange> > levelRangePairList = new List <KeyValuePair <ElementId, IFCRange> >();

            foreach (ElementId orphanLevelId in orphanLevels)
            {
                IFCLevelInfo levelInfo = ExporterCacheManager.LevelInfoCache.GetLevelInfo(exporterIFC, orphanLevelId);
                if (levelInfo == null)
                {
                    continue;
                }
                double   levelHeight = ExporterCacheManager.LevelInfoCache.FindHeight(orphanLevelId);
                IFCRange levelRange  = new IFCRange(levelInfo.Elevation, levelInfo.Elevation + levelHeight);

                List <KeyValuePair <Part, IFCRange> > splitPartRangeList = new List <KeyValuePair <Part, IFCRange> >();
                splitPartRangeList = ExporterCacheManager.HostPartsCache.Find(hostElement.Id, orphanLevelId);
                IFCRange highestRange = levelRange;
                foreach (KeyValuePair <Part, IFCRange> partRange in splitPartRangeList)
                {
                    if (partRange.Value.End > highestRange.End)
                    {
                        highestRange = partRange.Value;
                    }
                }
                levelRangePairList.Add(new KeyValuePair <ElementId, IFCRange>(orphanLevelId, highestRange));
            }
            if (levelRangePairList.Count > 0)
            {
                ExporterCacheManager.DummyHostCache.Register(hostElement.Id, levelRangePairList);
            }
        }
 /// <summary>
 /// Adds an IFCLevelInfo to the LevelsByElevation list, also updating the native cache item.
 /// </summary>
 /// <param name="exporterIFC">The exporter data object.</param>
 /// <param name="levelId">The level ElementId.</param>
 /// <param name="info">The IFCLevelInfo.</param>
 /// <param name="isBaseBuildingStorey">True if it is the levelId associated with the building storey.</param>
 public void AddLevelInfo(ExporterIFC exporterIFC, ElementId levelId, IFCLevelInfo info, bool isBaseBuildingStorey)
 {
    LevelsByElevation.Add(levelId);
    if (isBaseBuildingStorey)
       BuildingStoreysByElevation.Add(levelId);
    exporterIFC.AddBuildingStorey(levelId, info);
 }
        /// <summary>
        /// Exports an element as an IFC assembly.
        /// </summary>
        /// <param name="exporterIFC">The ExporterIFC object.</param>
        /// <param name="element">The element.</param>
        /// <param name="productWrapper">The ProductWrapper.</param>
        /// <returns>True if exported successfully, false otherwise.</returns>
        public static bool ExportAssemblyInstanceElement(ExporterIFC exporterIFC, AssemblyInstance element,
                                                         ProductWrapper productWrapper)
        {
            if (element == null)
            {
                return(false);
            }

            IFCFile file = exporterIFC.GetFile();

            using (IFCTransaction tr = new IFCTransaction(file))
            {
                IFCAnyHandle assemblyInstanceHnd = null;

                string             guid            = GUIDUtil.CreateGUID(element);
                IFCAnyHandle       ownerHistory    = exporterIFC.GetOwnerHistoryHandle();
                string             name            = NamingUtil.GetNameOverride(element, NamingUtil.GetIFCName(element));
                string             description     = NamingUtil.GetDescriptionOverride(element, null);
                string             objectType      = NamingUtil.GetObjectTypeOverride(element, exporterIFC.GetFamilyName());
                IFCAnyHandle       localPlacement  = null;
                IFCPlacementSetter placementSetter = null;
                IFCLevelInfo       levelInfo       = null;

                string        ifcEnumType;
                IFCExportType exportAs = ExporterUtil.GetExportType(exporterIFC, element, out ifcEnumType);
                if (exportAs == IFCExportType.ExportSystem)
                {
                    assemblyInstanceHnd = IFCInstanceExporter.CreateSystem(file, guid,
                                                                           ownerHistory, name, description, objectType);

                    // Create classification reference when System has classification filed name assigned to it
                    ClassificationUtil.CreateClassification(exporterIFC, file, element, assemblyInstanceHnd);

                    HashSet <IFCAnyHandle> relatedBuildings = new HashSet <IFCAnyHandle>();
                    relatedBuildings.Add(ExporterCacheManager.BuildingHandle);

                    IFCAnyHandle relServicesBuildings = IFCInstanceExporter.CreateRelServicesBuildings(file, GUIDUtil.CreateGUID(),
                                                                                                       exporterIFC.GetOwnerHistoryHandle(), null, null, assemblyInstanceHnd, relatedBuildings);
                }
                else
                {
                    using (placementSetter = IFCPlacementSetter.Create(exporterIFC, element, null, null, ExporterUtil.GetBaseLevelIdForElement(element)))
                    {
                        string       elementTag     = NamingUtil.GetTagOverride(element, NamingUtil.CreateIFCElementId(element));
                        IFCAnyHandle representation = null;

                        // We have limited support for exporting assemblies as other container types.
                        localPlacement = placementSetter.GetPlacement();
                        levelInfo      = placementSetter.GetLevelInfo();

                        switch (exportAs)
                        {
                        case IFCExportType.ExportCurtainWall:
                            assemblyInstanceHnd = IFCInstanceExporter.CreateCurtainWall(file, guid,
                                                                                        ownerHistory, name, description, objectType, localPlacement, representation, elementTag);
                            break;

                        case IFCExportType.ExportRamp:
                            IFCRampType rampPredefinedType = RampExporter.GetIFCRampType(ifcEnumType);
                            assemblyInstanceHnd = IFCInstanceExporter.CreateRamp(file, guid,
                                                                                 ownerHistory, name, description, objectType, localPlacement, representation, elementTag,
                                                                                 rampPredefinedType);
                            break;

                        case IFCExportType.ExportRoof:
                            IFCRoofType roofPredefinedType = RoofExporter.GetIFCRoofType(ifcEnumType);
                            assemblyInstanceHnd = IFCInstanceExporter.CreateRoof(file, guid,
                                                                                 ownerHistory, name, description, objectType, localPlacement, representation, elementTag,
                                                                                 roofPredefinedType);
                            break;

                        case IFCExportType.ExportStair:
                            IFCStairType stairPredefinedType = StairsExporter.GetIFCStairType(ifcEnumType);
                            assemblyInstanceHnd = IFCInstanceExporter.CreateStair(file, guid,
                                                                                  ownerHistory, name, description, objectType, localPlacement, representation, elementTag,
                                                                                  stairPredefinedType);
                            break;

                        case IFCExportType.ExportWall:
                            assemblyInstanceHnd = IFCInstanceExporter.CreateWall(file, guid,
                                                                                 ownerHistory, name, description, objectType, localPlacement, representation, elementTag);
                            break;

                        default:
                            IFCElementAssemblyType assemblyPredefinedType = GetPredefinedTypeFromObjectType(objectType);
                            assemblyInstanceHnd = IFCInstanceExporter.CreateElementAssembly(file, guid,
                                                                                            ownerHistory, name, description, objectType, localPlacement, representation, elementTag,
                                                                                            IFCAssemblyPlace.NotDefined, assemblyPredefinedType);
                            break;
                        }
                    }
                }

                if (assemblyInstanceHnd == null)
                {
                    return(false);
                }

                bool relateToLevel = (levelInfo != null);
                productWrapper.AddElement(element, assemblyInstanceHnd, levelInfo, null, relateToLevel);

                ExporterCacheManager.AssemblyInstanceCache.RegisterAssemblyInstance(element.Id, assemblyInstanceHnd);

                tr.Commit();
                return(true);
            }
        }