예제 #1
0
        /// <summary>
        /// Completes the export process by writing information stored incrementally during export to the file.
        /// </summary>
        /// <param name="exporterIFC">The IFC exporter object.</param>
        /// <param name="document">The document to export.</param>
        private void EndExport(ExporterIFC exporterIFC, Document document)
        {
            IFCFile file = exporterIFC.GetFile();
            IFCAnyHandle ownerHistory = exporterIFC.GetOwnerHistoryHandle();
                            
            using (IFCTransaction transaction = new IFCTransaction(file))
            {
                // In some cases, like multi-story stairs and ramps, we may have the same Pset used for multiple levels.
                // If ifcParams is null, re-use the property set.
                ISet<string> locallyUsedGUIDs = new HashSet<string>();
                
                // Relate Ducts and Pipes to their coverings (insulations and linings)
                foreach (ElementId ductOrPipeId in ExporterCacheManager.MEPCache.CoveredElementsCache)
                {
                    IFCAnyHandle ductOrPipeHandle = ExporterCacheManager.MEPCache.Find(ductOrPipeId);
                    if (IFCAnyHandleUtil.IsNullOrHasNoValue(ductOrPipeHandle))
                        continue;

                    HashSet<IFCAnyHandle> coveringHandles = new HashSet<IFCAnyHandle>();

                    try
                    {
                        ICollection<ElementId> liningIds = InsulationLiningBase.GetLiningIds(document, ductOrPipeId);
                        GetElementHandles(liningIds, coveringHandles);
                    }
                    catch
                    {
                    }

                    try
                    {
                        ICollection<ElementId> insulationIds = InsulationLiningBase.GetInsulationIds(document, ductOrPipeId);
                        GetElementHandles(insulationIds, coveringHandles);
                    }
                    catch
                    {
                    }

                    if (coveringHandles.Count > 0)
                        IFCInstanceExporter.CreateRelCoversBldgElements(file, GUIDUtil.CreateGUID(), ownerHistory, null, null, ductOrPipeHandle, coveringHandles);
                }

                // Relate stair components to stairs
                foreach (KeyValuePair<ElementId, StairRampContainerInfo> stairRamp in ExporterCacheManager.StairRampContainerInfoCache)
                {
                    StairRampContainerInfo stairRampInfo = stairRamp.Value;

                    IList<IFCAnyHandle> hnds = stairRampInfo.StairOrRampHandles;
                    for (int ii = 0; ii < hnds.Count; ii++)
                    {
                        IFCAnyHandle hnd = hnds[ii];
                        if (IFCAnyHandleUtil.IsNullOrHasNoValue(hnd))
                            continue;

                        IList<IFCAnyHandle> comps = stairRampInfo.Components[ii];
                        if (comps.Count == 0)
                            continue;

                        Element elem = document.GetElement(stairRamp.Key);
                        string guid = GUIDUtil.CreateSubElementGUID(elem, (int)IFCStairSubElements.ContainmentRelation);
                        if (locallyUsedGUIDs.Contains(guid))
                            guid = GUIDUtil.CreateGUID();
                        else
                            locallyUsedGUIDs.Add(guid);

                        ExporterUtil.RelateObjects(exporterIFC, guid, hnd, comps);
                    }
                }

                ProjectInfo projectInfo = document.ProjectInformation;
                IFCAnyHandle buildingHnd = ExporterCacheManager.BuildingHandle;

                // relate assembly elements to assemblies
                foreach (KeyValuePair<ElementId, AssemblyInstanceInfo> assemblyInfoEntry in ExporterCacheManager.AssemblyInstanceCache)
                {
                    AssemblyInstanceInfo assemblyInfo = assemblyInfoEntry.Value;
                    if (assemblyInfo == null)
                        continue;

                    IFCAnyHandle assemblyInstanceHandle = assemblyInfo.AssemblyInstanceHandle;
                    HashSet<IFCAnyHandle> elementHandles = assemblyInfo.ElementHandles;
                    if (elementHandles != null && assemblyInstanceHandle != null && elementHandles.Contains(assemblyInstanceHandle))
                        elementHandles.Remove(assemblyInstanceHandle);

                    if (assemblyInstanceHandle != null && elementHandles != null && elementHandles.Count != 0)
                    {
                        Element assemblyInstance = document.GetElement(assemblyInfoEntry.Key);
                        string guid = GUIDUtil.CreateSubElementGUID(assemblyInstance, (int)IFCAssemblyInstanceSubElements.RelContainedInSpatialStructure);

                        if (IFCAnyHandleUtil.IsSubTypeOf(assemblyInstanceHandle, IFCEntityType.IfcSystem))
                        {
                            IFCInstanceExporter.CreateRelAssignsToGroup(file, guid, ownerHistory, null, null, elementHandles, null, assemblyInstanceHandle);
                        }
                        else
                        {
                            ExporterUtil.RelateObjects(exporterIFC, guid, assemblyInstanceHandle, elementHandles);
                            // Set the PlacementRelTo of assembly elements to assembly instance.
                            IFCAnyHandle assemblyPlacement = IFCAnyHandleUtil.GetObjectPlacement(assemblyInstanceHandle);
                            AssemblyInstanceExporter.SetLocalPlacementsRelativeToAssembly(exporterIFC, assemblyPlacement, elementHandles);
                        }

                        // We don't do this in RegisterAssemblyElement because we want to make sure that the IfcElementAssembly has been created.
                        ExporterCacheManager.ElementsInAssembliesCache.UnionWith(elementHandles);
                    }                  
                }

                // relate group elements to groups
                foreach (KeyValuePair<ElementId, GroupInfo> groupEntry in ExporterCacheManager.GroupCache)
                {
                    GroupInfo groupInfo = groupEntry.Value;
                    if (groupInfo == null)
                        continue;

                    if (groupInfo.GroupHandle != null && groupInfo.ElementHandles != null &&
                        groupInfo.ElementHandles.Count != 0)
                    {
                        Element group = document.GetElement(groupEntry.Key);
                        string guid = GUIDUtil.CreateSubElementGUID(group, (int)IFCGroupSubElements.RelAssignsToGroup);

                        IFCAnyHandle groupHandle = groupInfo.GroupHandle;
                        HashSet<IFCAnyHandle> elementHandles = groupInfo.ElementHandles;
                        if (elementHandles != null && groupHandle != null && elementHandles.Contains(groupHandle))
                            elementHandles.Remove(groupHandle);

                        if (elementHandles != null && groupHandle != null && elementHandles.Count > 0)
                        {
                            IFCInstanceExporter.CreateRelAssignsToGroup(file, guid, ownerHistory, null, null, elementHandles, null, groupHandle);
                        }
                    }
                }

                // create spatial structure holder
                ICollection<IFCAnyHandle> relatedElements = exporterIFC.GetRelatedElements();
                if (relatedElements.Count > 0)
                {
                    HashSet<IFCAnyHandle> relatedElementSet = new HashSet<IFCAnyHandle>(relatedElements);
                    string guid = GUIDUtil.CreateSubElementGUID(projectInfo, (int)IFCBuildingSubElements.RelContainedInSpatialStructure);
                    IFCInstanceExporter.CreateRelContainedInSpatialStructure(file, guid,
                        ownerHistory, null, null, relatedElementSet, buildingHnd);
                }

                ICollection<IFCAnyHandle> relatedProducts = exporterIFC.GetRelatedProducts();
                if (relatedProducts.Count > 0)
                {
                    string guid = GUIDUtil.CreateSubElementGUID(projectInfo, (int)IFCBuildingSubElements.RelAggregatesProducts);
                    ExporterCacheManager.ContainmentCache.SetGUIDForRelation(buildingHnd, guid);
                    ExporterCacheManager.ContainmentCache.AddRelations(buildingHnd, relatedProducts);
                }

                // create a default site if we have latitude and longitude information.
                if (IFCAnyHandleUtil.IsNullOrHasNoValue(exporterIFC.GetSite()))
                {
                    using (ProductWrapper productWrapper = ProductWrapper.Create(exporterIFC, true))
                    {
                        SiteExporter.ExportDefaultSite(exporterIFC, document, productWrapper);
                    }
                }

                IFCAnyHandle siteHandle = exporterIFC.GetSite();
                if (!IFCAnyHandleUtil.IsNullOrHasNoValue(siteHandle))
                {
                    ExporterCacheManager.ContainmentCache.AddRelation(exporterIFC.GetProject(), siteHandle);

                    // assoc. site to the building.
                    ExporterCacheManager.ContainmentCache.AddRelation(siteHandle, buildingHnd);

                    ExporterUtil.UpdateBuildingRelToPlacement(buildingHnd, siteHandle);
                }
                else
                {
                    // relate building and project if no site
                    ExporterCacheManager.ContainmentCache.AddRelation(exporterIFC.GetProject(), buildingHnd);
                }

                // relate levels and products.
                RelateLevels(exporterIFC, document);

                // relate objects in containment cache.
                foreach (KeyValuePair<IFCAnyHandle, ICollection<IFCAnyHandle>> container in ExporterCacheManager.ContainmentCache)
                {
                    if (container.Value.Count() > 0)
                    {
                        string relationGUID = ExporterCacheManager.ContainmentCache.GetGUIDForRelation(container.Key);
                        ExporterUtil.RelateObjects(exporterIFC, relationGUID, container.Key, container.Value);
                    }
                }

                // These elements are created internally, but we allow custom property sets for them.  Create them here.
                using (ProductWrapper productWrapper = ProductWrapper.Create(exporterIFC, true))
                {
                    productWrapper.AddBuilding(projectInfo, buildingHnd);
                    if (projectInfo != null)
                        ExporterUtil.ExportRelatedProperties(exporterIFC, projectInfo, productWrapper);
                }

                // create material layer associations
                foreach (IFCAnyHandle materialSetLayerUsageHnd in ExporterCacheManager.MaterialLayerRelationsCache.Keys)
                {
                    IFCInstanceExporter.CreateRelAssociatesMaterial(file, GUIDUtil.CreateGUID(), ownerHistory,
                        null, null, ExporterCacheManager.MaterialLayerRelationsCache[materialSetLayerUsageHnd],
                        materialSetLayerUsageHnd);
                }

                // create material associations
                foreach (IFCAnyHandle materialHnd in ExporterCacheManager.MaterialRelationsCache.Keys)
                {
                    IFCInstanceExporter.CreateRelAssociatesMaterial(file, GUIDUtil.CreateGUID(), ownerHistory,
                        null, null, ExporterCacheManager.MaterialRelationsCache[materialHnd], materialHnd);
                }

                // create type relations
                foreach (IFCAnyHandle typeObj in ExporterCacheManager.TypeRelationsCache.Keys)
                {
                    IFCInstanceExporter.CreateRelDefinesByType(file, GUIDUtil.CreateGUID(), ownerHistory,
                        null, null, ExporterCacheManager.TypeRelationsCache[typeObj], typeObj);
                }

                // create type property relations
                foreach (TypePropertyInfo typePropertyInfo in ExporterCacheManager.TypePropertyInfoCache.Values)
                {
                    if (typePropertyInfo.AssignedToType)
                        continue;

                    ICollection<IFCAnyHandle> propertySets = typePropertyInfo.PropertySets;
                    ISet<IFCAnyHandle> elements = typePropertyInfo.Elements;

                    if (elements.Count == 0)
                        continue;

                    foreach (IFCAnyHandle propertySet in propertySets)
                    {
                        try
                        {
                            IFCInstanceExporter.CreateRelDefinesByProperties(file, GUIDUtil.CreateGUID(), ownerHistory,
                                null, null, elements, propertySet);
                        }
                        catch
                        {
                        }
                    }
                }

                // create space boundaries
                foreach (SpaceBoundary boundary in ExporterCacheManager.SpaceBoundaryCache)
                {
                    SpatialElementExporter.ProcessIFCSpaceBoundary(exporterIFC, boundary, file);
                }

                // create wall/wall connectivity objects
                if (ExporterCacheManager.WallConnectionDataCache.Count > 0)
                {
                    IList<IDictionary<ElementId, IFCAnyHandle>> hostObjects = exporterIFC.GetHostObjects();
                    List<int> relatingPriorities = new List<int>();
                    List<int> relatedPriorities = new List<int>();

                    foreach (WallConnectionData wallConnectionData in ExporterCacheManager.WallConnectionDataCache)
                    {
                        foreach (IDictionary<ElementId, IFCAnyHandle> mapForLevel in hostObjects)
                        {
                            IFCAnyHandle wallElementHandle, otherElementHandle;
                            if (!mapForLevel.TryGetValue(wallConnectionData.FirstId, out wallElementHandle))
                                continue;
                            if (!mapForLevel.TryGetValue(wallConnectionData.SecondId, out otherElementHandle))
                                continue;

                            // NOTE: Definition of RelConnectsPathElements has the connection information reversed
                            // with respect to the order of the paths.
                            string connectionName = IFCAnyHandleUtil.GetStringAttribute(wallElementHandle, "GlobalId") + "|" 
                                                        + IFCAnyHandleUtil.GetStringAttribute(otherElementHandle, "GlobalId");
                            string connectionType = "Structural";   // Assigned as Description
                            IFCInstanceExporter.CreateRelConnectsPathElements(file, GUIDUtil.CreateGUID(), ownerHistory,
                                connectionName, connectionType, wallConnectionData.ConnectionGeometry, wallElementHandle, otherElementHandle, relatingPriorities,
                                relatedPriorities, wallConnectionData.SecondConnectionType, wallConnectionData.FirstConnectionType);
                        }
                    }
                }

                // create Zones
                {
                    string relAssignsToGroupName = "Spatial Zone Assignment";
                    foreach (string zoneName in ExporterCacheManager.ZoneInfoCache.Keys)
                    {
                        ZoneInfo zoneInfo = ExporterCacheManager.ZoneInfoCache.Find(zoneName);
                        if (zoneInfo != null)
                        {
                            IFCAnyHandle zoneHandle = IFCInstanceExporter.CreateZone(file, GUIDUtil.CreateGUID(), ownerHistory,
                                zoneName, zoneInfo.Description, zoneInfo.ObjectType);
                            IFCInstanceExporter.CreateRelAssignsToGroup(file, GUIDUtil.CreateGUID(), ownerHistory,
                                relAssignsToGroupName, null, zoneInfo.RoomHandles, null, zoneHandle);

                            HashSet<IFCAnyHandle> zoneHnds = new HashSet<IFCAnyHandle>();
                            zoneHnds.Add(zoneHandle);

                            foreach (KeyValuePair<string, IFCAnyHandle> classificationReference in zoneInfo.ClassificationReferences)
                            {
                                IFCAnyHandle relAssociates = IFCInstanceExporter.CreateRelAssociatesClassification(file, GUIDUtil.CreateGUID(),
                                    ownerHistory, classificationReference.Key, "", zoneHnds, classificationReference.Value);
                            }

                            if (!IFCAnyHandleUtil.IsNullOrHasNoValue(zoneInfo.EnergyAnalysisProperySetHandle))
                            {
                                IFCInstanceExporter.CreateRelDefinesByProperties(file, GUIDUtil.CreateGUID(),
                                    ownerHistory, null, null, zoneHnds, zoneInfo.EnergyAnalysisProperySetHandle);
                            }

                            if (!IFCAnyHandleUtil.IsNullOrHasNoValue(zoneInfo.ZoneCommonProperySetHandle))
                            {
                                IFCInstanceExporter.CreateRelDefinesByProperties(file, GUIDUtil.CreateGUID(),
                                    ownerHistory, null, null, zoneHnds, zoneInfo.ZoneCommonProperySetHandle);
                            }
                        }
                    }
                }

                // create Space Occupants
                {
                    foreach (string spaceOccupantName in ExporterCacheManager.SpaceOccupantInfoCache.Keys)
                    {
                        SpaceOccupantInfo spaceOccupantInfo = ExporterCacheManager.SpaceOccupantInfoCache.Find(spaceOccupantName);
                        if (spaceOccupantInfo != null)
                        {
                            IFCAnyHandle person = IFCInstanceExporter.CreatePerson(file, null, spaceOccupantName, null, null, null, null, null, null);
                            IFCAnyHandle spaceOccupantHandle = IFCInstanceExporter.CreateOccupant(file, GUIDUtil.CreateGUID(),
                                ownerHistory, null, null, spaceOccupantName, person, IFCOccupantType.NotDefined);
                            IFCInstanceExporter.CreateRelOccupiesSpaces(file, GUIDUtil.CreateGUID(), ownerHistory,
                                null, null, spaceOccupantInfo.RoomHandles, null, spaceOccupantHandle, null);

                            HashSet<IFCAnyHandle> spaceOccupantHandles = new HashSet<IFCAnyHandle>();
                            spaceOccupantHandles.Add(spaceOccupantHandle);

                            foreach (KeyValuePair<string, IFCAnyHandle> classificationReference in spaceOccupantInfo.ClassificationReferences)
                            {
                                IFCAnyHandle relAssociates = IFCInstanceExporter.CreateRelAssociatesClassification(file, GUIDUtil.CreateGUID(),
                                    ownerHistory, classificationReference.Key, "", spaceOccupantHandles, classificationReference.Value);
                            }

                            if (spaceOccupantInfo.SpaceOccupantProperySetHandle != null && spaceOccupantInfo.SpaceOccupantProperySetHandle.HasValue)
                            {
                                IFCAnyHandle relHnd = IFCInstanceExporter.CreateRelDefinesByProperties(file, GUIDUtil.CreateGUID(),
                                    ownerHistory, null, null, spaceOccupantHandles, spaceOccupantInfo.SpaceOccupantProperySetHandle);
                            }
                        }
                    }
                }

                // Create systems.
                HashSet<IFCAnyHandle> relatedBuildings = new HashSet<IFCAnyHandle>();
                relatedBuildings.Add(buildingHnd);

                using (ProductWrapper productWrapper = ProductWrapper.Create(exporterIFC, true))
                {
                    foreach (KeyValuePair<ElementId, ISet<IFCAnyHandle>> system in ExporterCacheManager.SystemsCache.BuiltInSystemsCache)
                    {
                        MEPSystem systemElem = document.GetElement(system.Key) as MEPSystem;
                        if (systemElem == null)
                            continue;

                        Element baseEquipment = systemElem.BaseEquipment;
                        if (baseEquipment != null)
                        {
                            IFCAnyHandle memberHandle = ExporterCacheManager.MEPCache.Find(baseEquipment.Id);
                            if (!IFCAnyHandleUtil.IsNullOrHasNoValue(memberHandle))
                                system.Value.Add(memberHandle);
                        }

                        ElementType systemElemType = document.GetElement(systemElem.GetTypeId()) as ElementType;
                        string name = NamingUtil.GetNameOverride(systemElem, systemElem.Name);
                        string desc = NamingUtil.GetDescriptionOverride(systemElem, null);
                        string objectType = NamingUtil.GetObjectTypeOverride(systemElem,
                            (systemElemType != null) ? systemElemType.Name : "");

                        string systemGUID = GUIDUtil.CreateGUID(systemElem);
                        IFCAnyHandle systemHandle = IFCInstanceExporter.CreateSystem(file, systemGUID,
                            ownerHistory, name, desc, objectType);
                        
                        // Create classification reference when System has classification filed name assigned to it
                        ClassificationUtil.CreateClassification(exporterIFC, file, systemElem, systemHandle);
                        
                        productWrapper.AddSystem(systemElem, systemHandle);

                        IFCAnyHandle relServicesBuildings = IFCInstanceExporter.CreateRelServicesBuildings(file, GUIDUtil.CreateGUID(),
                            ownerHistory, null, null, systemHandle, relatedBuildings);

                        IFCObjectType? objType = null;
                        if (!ExporterCacheManager.ExportOptionsCache.ExportAsCoordinationView2)
                            objType = IFCObjectType.Product;
                        IFCAnyHandle relAssignsToGroup = IFCInstanceExporter.CreateRelAssignsToGroup(file, GUIDUtil.CreateGUID(),
                            ownerHistory, null, null, system.Value, objType, systemHandle);
                    }
                }

                using (ProductWrapper productWrapper = ProductWrapper.Create(exporterIFC, true))
                {
                    foreach (KeyValuePair<ElementId, ISet<IFCAnyHandle>> entries in ExporterCacheManager.SystemsCache.ElectricalSystemsCache)
                    {
                        ElementId systemId = entries.Key;
                        MEPSystem systemElem = document.GetElement(systemId) as MEPSystem;
                        if (systemElem == null)
                            continue;

                        Element baseEquipment = systemElem.BaseEquipment;
                        if (baseEquipment != null)
                        {
                            IFCAnyHandle memberHandle = ExporterCacheManager.MEPCache.Find(baseEquipment.Id);
                            if (!IFCAnyHandleUtil.IsNullOrHasNoValue(memberHandle))
                                entries.Value.Add(memberHandle);
                        }

                        // The Elements property below can throw an InvalidOperationException in some cases, which could
                        // crash the export.  Protect against this without having too generic a try/catch block.
                        try
                        {
                            ElementSet members = systemElem.Elements;
                            foreach (Element member in members)
                            {
                                IFCAnyHandle memberHandle = ExporterCacheManager.MEPCache.Find(member.Id);
                                if (!IFCAnyHandleUtil.IsNullOrHasNoValue(memberHandle))
                                    entries.Value.Add(memberHandle);
                            }
                        }
                        catch
                        {
                        }

                        if (entries.Value.Count == 0)
                            continue;

                        ElementType systemElemType = document.GetElement(systemElem.GetTypeId()) as ElementType;
                        string name = NamingUtil.GetNameOverride(systemElem, systemElem.Name);
                        string desc = NamingUtil.GetDescriptionOverride(systemElem, null);
                        string objectType = NamingUtil.GetObjectTypeOverride(systemElem,
                            (systemElemType != null) ? systemElemType.Name : "");

                        string systemGUID = GUIDUtil.CreateGUID(systemElem);
                        IFCAnyHandle systemHandle = IFCInstanceExporter.CreateSystem(file,
                            systemGUID, ownerHistory, name, desc, objectType);

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

                        productWrapper.AddSystem(systemElem, systemHandle);

                        IFCAnyHandle relServicesBuildings = IFCInstanceExporter.CreateRelServicesBuildings(file, GUIDUtil.CreateGUID(),
                            ownerHistory, null, null, systemHandle, relatedBuildings);

                        IFCObjectType? objType = null;
                        if (!ExporterCacheManager.ExportOptionsCache.ExportAsCoordinationView2)
                            objType = IFCObjectType.Product;
                        IFCAnyHandle relAssignsToGroup = IFCInstanceExporter.CreateRelAssignsToGroup(file, GUIDUtil.CreateGUID(),
                            ownerHistory, null, null, entries.Value, objType, systemHandle);
                    }
                }

                // Add presentation layer assignments - this is in addition to those added in EndExportInternal, and will
                // eventually replace the internal routine.
                foreach (KeyValuePair<string, ICollection<IFCAnyHandle>> presentationLayerSet in ExporterCacheManager.PresentationLayerSetCache)
                {
                    ISet<IFCAnyHandle> validHandles = new HashSet<IFCAnyHandle>();
                    foreach (IFCAnyHandle handle in presentationLayerSet.Value)
                    {
                        if (!IFCAnyHandleUtil.IsNullOrHasNoValue(handle))
                            validHandles.Add(handle);
                    }

                    if (validHandles.Count > 0)
                        IFCInstanceExporter.CreatePresentationLayerAssignment(file, presentationLayerSet.Key, null, validHandles, null);
                }

                // Add door/window openings.
                ExporterCacheManager.DoorWindowDelayedOpeningCreatorCache.ExecuteCreators(exporterIFC, document);

                foreach (SpaceInfo spaceInfo in ExporterCacheManager.SpaceInfoCache.SpaceInfos.Values)
                {
                    if (spaceInfo.RelatedElements.Count > 0)
                    {
                        IFCInstanceExporter.CreateRelContainedInSpatialStructure(file, GUIDUtil.CreateGUID(), ownerHistory,
                            null, null, spaceInfo.RelatedElements, spaceInfo.SpaceHandle);
                    }
                }

                // Potentially modify elements with GUID values.
                if (ExporterCacheManager.GUIDsToStoreCache.Count > 0 && !ExporterCacheManager.ExportOptionsCache.ExportingLink)
                {
                    using (SubTransaction st = new SubTransaction(document))
                    {
                        st.Start();
                        foreach (KeyValuePair<KeyValuePair<Element, BuiltInParameter>, string> elementAndGUID in ExporterCacheManager.GUIDsToStoreCache)
                        {
                            if (elementAndGUID.Key.Key == null || elementAndGUID.Key.Value == BuiltInParameter.INVALID || elementAndGUID.Value == null)
                                continue;

                            ParameterUtil.SetStringParameter(elementAndGUID.Key.Key, elementAndGUID.Key.Value, elementAndGUID.Value);
                        }
                        st.Commit();
                    }
                }

                // Allow native code to remove some unused handles, assign presentation map information and clear internal caches.
                ExporterIFCUtils.EndExportInternal(exporterIFC);

                //create header

                ExportOptionsCache exportOptionsCache = ExporterCacheManager.ExportOptionsCache;

                string coordinationView = null;
                if (exportOptionsCache.ExportAsCoordinationView2)
                    coordinationView = "CoordinationView_V2.0";
                else
                    coordinationView = "CoordinationView";

                List<string> descriptions = new List<string>();
                if (ExporterCacheManager.ExportOptionsCache.ExportAs2x2 || ExporterUtil.DoCodeChecking(exportOptionsCache))
                {
                    descriptions.Add("IFC2X_PLATFORM");
                }
                else
                {
                    string currentLine;
                    if (ExporterUtil.IsFMHandoverView())
                    {
                        currentLine = string.Format("ViewDefinition [{0}{1}{2}{3}]",
                           coordinationView,
                           exportOptionsCache.ExportBaseQuantities ? ", QuantityTakeOffAddOnView" : "",
                           ", ", "FMHandOverView");
                    }
                    else
                    {
                        currentLine = string.Format("ViewDefinition [{0}{1}]",
                           coordinationView,
                           exportOptionsCache.ExportBaseQuantities ? ", QuantityTakeOffAddOnView" : "");
                    }

                    descriptions.Add(currentLine);
                  
                }

                string projectNumber = (projectInfo != null) ? projectInfo.Number : null;
                string projectName = (projectInfo != null) ? projectInfo.Name : null;
                string projectStatus = (projectInfo != null) ? projectInfo.Status : null;

                if (projectNumber == null)
                    projectNumber = string.Empty;
                if (projectName == null)
                    projectName = exportOptionsCache.FileName;
                if (projectStatus == null)
                    projectStatus = string.Empty;

                IFCAnyHandle project = exporterIFC.GetProject();
                if (!IFCAnyHandleUtil.IsNullOrHasNoValue(project))
                    IFCAnyHandleUtil.UpdateProject(project, projectNumber, projectName, projectStatus);

                IFCInstanceExporter.CreateFileSchema(file);
                IFCInstanceExporter.CreateFileDescription(file, descriptions);
                // Get stored File Header information from the UI and use it for export
                IFCFileHeader fHeader = new IFCFileHeader();
                IFCFileHeaderItem fHItem = null;

                fHeader.GetSavedFileHeader(document, out fHItem);

                List<string> author = new List<string>();
                if (String.IsNullOrEmpty(fHItem.AuthorName) == false)
                {
                    author.Add(fHItem.AuthorName);
                    if (String.IsNullOrEmpty(fHItem.AuthorEmail) == false)
                        author.Add(fHItem.AuthorEmail);
                }
                else
                    author.Add(String.Empty);

                List<string> organization = new List<string>();
                if (String.IsNullOrEmpty(fHItem.Organization) == false)
                    organization.Add(fHItem.Organization);
                else
                    organization.Add(String.Empty);

                string versionInfos = document.Application.VersionBuild + " - " + ExporterCacheManager.ExportOptionsCache.ExporterVersion + " - " + ExporterCacheManager.ExportOptionsCache.ExporterUIVersion;

                if (fHItem.Authorization == null)
                    fHItem.Authorization = String.Empty;

                IFCInstanceExporter.CreateFileName(file, projectNumber, author, organization, document.Application.VersionName,
                    versionInfos, fHItem.Authorization);

                transaction.Commit();

                IFCFileWriteOptions writeOptions = new IFCFileWriteOptions();
                writeOptions.FileName = exportOptionsCache.FileName;
                writeOptions.FileFormat = exportOptionsCache.IFCFileFormat;
                if (writeOptions.FileFormat == IFCFileFormat.IfcXML || writeOptions.FileFormat == IFCFileFormat.IfcXMLZIP)
                {
                    writeOptions.XMLConfigFileName = Path.Combine(ExporterUtil.RevitProgramPath, "EDM\\ifcXMLconfiguration.xml");
                }
                file.Write(writeOptions);

                // Reuse almost all of the information above to write out extra copies of the IFC file.
                if (exportOptionsCache.ExportingLink)
                {
                    int numRevitLinkInstances = exportOptionsCache.GetNumLinkInstanceInfos();
                    for (int ii = 1; ii < numRevitLinkInstances; ii++)
                    {
                        Transform linkTrf = ExporterCacheManager.ExportOptionsCache.GetLinkInstanceTransform(ii);
                        IFCAnyHandle relativePlacement = ExporterUtil.CreateAxis2Placement3D(file, linkTrf.Origin, linkTrf.BasisZ, linkTrf.BasisX);
                        ExporterUtil.UpdateBuildingRelativePlacement(buildingHnd, relativePlacement);

                        writeOptions.FileName = exportOptionsCache.GetLinkInstanceFileName(ii);
                        file.Write(writeOptions);
                    }
                }
            }
        }
예제 #2
0
파일: Exporter.cs 프로젝트: whztt07/BIM-IFC
        /// <summary>
        /// Completes the export process by writing information stored incrementally during export to the file.
        /// </summary>
        /// <param name="exporterIFC">The IFC exporter object.</param>
        /// <param name="document">The document to export.</param>
        private void EndExport(ExporterIFC exporterIFC, Document document)
        {
            IFCFile file = exporterIFC.GetFile();
            using (IFCTransaction transaction = new IFCTransaction(file))
            {
                foreach (KeyValuePair<ElementId, StairRampContainerInfo> stairRamp in ExporterCacheManager.StairRampContainerInfoCache)
                {
                    StairRampContainerInfo stairRampInfo = stairRamp.Value;

                    IList<IFCAnyHandle> hnds = stairRampInfo.StairOrRampHandles;
                    for (int ii = 0; ii < hnds.Count; ii++)
                    {
                        IFCAnyHandle hnd = hnds[ii];
                        if (IFCAnyHandleUtil.IsNullOrHasNoValue(hnd))
                            continue;

                        IList<IFCAnyHandle> comps = stairRampInfo.Components[ii];
                        if (comps.Count == 0)
                            continue;

                        Element elem = document.GetElement(stairRamp.Key);
                        string guid = ExporterIFCUtils.CreateSubElementGUID(elem, (int) IFCStairSubElements.ContainmentRelation);
                        ExporterUtil.RelateObjects(exporterIFC, guid, hnd, comps);
                    }
                }
                
                ProjectInfo projectInfo = document.ProjectInformation;
                    
                // relate assembly elements to assemblies
                foreach (KeyValuePair<ElementId, AssemblyInstanceInfo> assemblyInfoEntry in ExporterCacheManager.AssemblyInstanceCache)
                {
                    AssemblyInstanceInfo assemblyInfo = assemblyInfoEntry.Value;
                    if (assemblyInfo == null)
                        continue;

                    if (assemblyInfo.AssemblyInstanceHandle != null && assemblyInfo.ElementHandles != null &&
                        assemblyInfo.ElementHandles.Count != 0)
                    {
                        Element assemblyInstance = document.GetElement(assemblyInfoEntry.Key);
                        string guid = ExporterIFCUtils.CreateSubElementGUID(assemblyInstance, (int)IFCAssemblyInstanceSubElements.RelContainedInSpatialStructure);
                        ExporterUtil.RelateObjects(exporterIFC, guid, assemblyInfo.AssemblyInstanceHandle, assemblyInfo.ElementHandles);
                    }
                }

                // create spatial structure holder
                ICollection<IFCAnyHandle> relatedElements = exporterIFC.GetRelatedElements();
                if (relatedElements.Count > 0)
                {
                    HashSet<IFCAnyHandle> relatedElementSet = new HashSet<IFCAnyHandle>(relatedElements);
                    IFCInstanceExporter.CreateRelContainedInSpatialStructure(file,
                        ExporterIFCUtils.CreateSubElementGUID(projectInfo, (int)IFCBuildingSubElements.RelContainedInSpatialStructure),
                        exporterIFC.GetOwnerHistoryHandle(), null, null, relatedElementSet, exporterIFC.GetBuilding());
                }

                ICollection<IFCAnyHandle> relatedProducts = exporterIFC.GetRelatedProducts();
                if (relatedProducts.Count > 0)
                {
                    string guid = ExporterIFCUtils.CreateSubElementGUID(projectInfo, (int)IFCBuildingSubElements.RelAggregatesProducts);
                    ExporterUtil.RelateObjects(exporterIFC, guid, exporterIFC.GetBuilding(), relatedProducts);
                }

                // create a default site if we have latitude and longitude information.
                if (IFCAnyHandleUtil.IsNullOrHasNoValue(exporterIFC.GetSite()))
                {
                    using (IFCProductWrapper productWrapper = IFCProductWrapper.Create(exporterIFC, true))
                    {
                        SiteExporter.ExportDefaultSite(exporterIFC, document, productWrapper);
                    }
                }

                IFCAnyHandle siteHandle = exporterIFC.GetSite();
                if (!IFCAnyHandleUtil.IsNullOrHasNoValue(siteHandle))
                {
                    ExporterUtil.RelateObject(exporterIFC, exporterIFC.GetProject(), siteHandle);

                    // assoc. site to the building.
                    ExporterUtil.RelateObject(exporterIFC, siteHandle, exporterIFC.GetBuilding());

                    ExporterIFCUtils.UpdateBuildingPlacement(exporterIFC);
                }
                else
                {
                    // relate building and project if no site
                    ExporterUtil.RelateObject(exporterIFC, exporterIFC.GetProject(), exporterIFC.GetBuilding());
                }

                // relate levels and products.
                RelateLevels(exporterIFC, document);

                // These elements are created internally, but we allow custom property sets for them.  Create them here.
                using (IFCProductWrapper productWrapper = IFCProductWrapper.Create(exporterIFC, true))
                {
                    IFCAnyHandle buildingHnd = exporterIFC.GetBuilding();
                    productWrapper.AddBuilding(buildingHnd);
                    ExportElementProperties(exporterIFC, document.ProjectInformation, productWrapper);
                    PropertyUtil.CreateInternalRevitPropertySets(exporterIFC, document.ProjectInformation, productWrapper);
                }

                // create material layer associations
                foreach (IFCAnyHandle materialSetLayerUsageHnd in ExporterCacheManager.MaterialLayerRelationsCache.Keys)
                {
                    IFCInstanceExporter.CreateRelAssociatesMaterial(file, ExporterIFCUtils.CreateGUID(), exporterIFC.GetOwnerHistoryHandle(),
                        null, null, ExporterCacheManager.MaterialLayerRelationsCache[materialSetLayerUsageHnd],
                        materialSetLayerUsageHnd);
                }

                // create material associations
                foreach (IFCAnyHandle materialHnd in ExporterCacheManager.MaterialRelationsCache.Keys)
                {
                    IFCInstanceExporter.CreateRelAssociatesMaterial(file, ExporterIFCUtils.CreateGUID(), exporterIFC.GetOwnerHistoryHandle(),
                        null, null, ExporterCacheManager.MaterialRelationsCache[materialHnd], materialHnd);
                }

                // create type relations
                foreach (IFCAnyHandle typeObj in ExporterCacheManager.TypeRelationsCache.Keys)
                {
                    IFCInstanceExporter.CreateRelDefinesByType(file, ExporterIFCUtils.CreateGUID(), exporterIFC.GetOwnerHistoryHandle(),
                        null, null,  ExporterCacheManager.TypeRelationsCache[typeObj], typeObj);
                }

                // create type property relations
                foreach (TypePropertyInfo typePropertyInfo in ExporterCacheManager.TypePropertyInfoCache.Values)
                {
                    HashSet<IFCAnyHandle> propertySets = typePropertyInfo.PropertySets;
                    HashSet<IFCAnyHandle> elements = typePropertyInfo.Elements;

                    foreach (IFCAnyHandle propertySet in propertySets)
                    {
                        IFCInstanceExporter.CreateRelDefinesByProperties(file, ExporterIFCUtils.CreateGUID(), exporterIFC.GetOwnerHistoryHandle(),
                            null, null, elements, propertySet);
                    }
                }

                // create space boundaries
                foreach (SpaceBoundary boundary in ExporterCacheManager.SpaceBoundaryCache)
                {
                    SpatialElementExporter.ProcessIFCSpaceBoundary(exporterIFC, boundary, file);
                }

                // create wall/wall connectivity objects
                if (ExporterCacheManager.WallConnectionDataCache.Count > 0)
                {
                    IList<IDictionary<ElementId, IFCAnyHandle>> hostObjects = exporterIFC.GetHostObjects();
                    List<int> relatingPriorities = new List<int>();
                    List<int> relatedPriorities = new List<int>();

                    foreach (WallConnectionData wallConnectionData in ExporterCacheManager.WallConnectionDataCache)
                    {
                        foreach (IDictionary<ElementId, IFCAnyHandle> mapForLevel in hostObjects)
                        {
                            IFCAnyHandle wallElementHandle, otherElementHandle;
                            if (!mapForLevel.TryGetValue(wallConnectionData.FirstId, out wallElementHandle))
                                continue;
                            if (!mapForLevel.TryGetValue(wallConnectionData.SecondId, out otherElementHandle))
                                continue;

                            // NOTE: Definition of RelConnectsPathElements has the connection information reversed
                            // with respect to the order of the paths.
                            IFCInstanceExporter.CreateRelConnectsPathElements(file, ExporterIFCUtils.CreateGUID(), exporterIFC.GetOwnerHistoryHandle(),
                                null, null, wallConnectionData.ConnectionGeometry, wallElementHandle, otherElementHandle, relatingPriorities,
                                relatedPriorities, wallConnectionData.SecondConnectionType, wallConnectionData.FirstConnectionType);
                        }
                    }
                }

                // create Zones
                {
                    string relAssignsToGroupName = "Spatial Zone Assignment";
                    foreach (string zoneName in ExporterCacheManager.ZoneInfoCache.Keys)
                    {
                        ZoneInfo zoneInfo = ExporterCacheManager.ZoneInfoCache.Find(zoneName);
                        if (zoneInfo != null)
                        {
                            IFCAnyHandle zoneHandle = IFCInstanceExporter.CreateZone(file, ExporterIFCUtils.CreateGUID(), exporterIFC.GetOwnerHistoryHandle(),
                                zoneName, zoneInfo.ObjectType, zoneInfo.Description);
                            IFCInstanceExporter.CreateRelAssignsToGroup(file, ExporterIFCUtils.CreateGUID(), exporterIFC.GetOwnerHistoryHandle(),
                                relAssignsToGroupName, null, zoneInfo.RoomHandles, null, zoneHandle);

                            HashSet<IFCAnyHandle> zoneHnds = new HashSet<IFCAnyHandle>();
                            zoneHnds.Add(zoneHandle);
                                
                            foreach (KeyValuePair<string, IFCAnyHandle> classificationReference in zoneInfo.ClassificationReferences)
                            {
                                IFCAnyHandle relAssociates = IFCInstanceExporter.CreateRelAssociatesClassification(file, ExporterIFCUtils.CreateGUID(),
                                    exporterIFC.GetOwnerHistoryHandle(), classificationReference.Key, "", zoneHnds, classificationReference.Value);
                            }

                            if (zoneInfo.EnergyAnalysisProperySetHandle != null && zoneInfo.EnergyAnalysisProperySetHandle.HasValue)
                            {
                                IFCAnyHandle relHnd = IFCInstanceExporter.CreateRelDefinesByProperties(file, ExporterIFCUtils.CreateGUID(),
                                    exporterIFC.GetOwnerHistoryHandle(), null, null, zoneHnds, zoneInfo.EnergyAnalysisProperySetHandle);
                            }

                        }
                    }
                }

                // create Space Occupants
                {
                    foreach (string spaceOccupantName in ExporterCacheManager.SpaceOccupantInfoCache.Keys)
                    {
                        SpaceOccupantInfo spaceOccupantInfo = ExporterCacheManager.SpaceOccupantInfoCache.Find(spaceOccupantName);
                        if (spaceOccupantInfo != null)
                        {
                            IFCAnyHandle person = IFCInstanceExporter.CreatePerson(file, null, spaceOccupantName, null, null, null, null, null, null);
                            IFCAnyHandle spaceOccupantHandle = IFCInstanceExporter.CreateOccupant(file, ExporterIFCUtils.CreateGUID(), 
                                exporterIFC.GetOwnerHistoryHandle(), null, null, spaceOccupantName, person, IFCOccupantType.NotDefined);
                            IFCInstanceExporter.CreateRelOccupiesSpaces(file, ExporterIFCUtils.CreateGUID(), exporterIFC.GetOwnerHistoryHandle(),
                                null, null, spaceOccupantInfo.RoomHandles, null, spaceOccupantHandle, null);

                            HashSet<IFCAnyHandle> spaceOccupantHandles = new HashSet<IFCAnyHandle>();
                            spaceOccupantHandles.Add(spaceOccupantHandle);

                            foreach (KeyValuePair<string, IFCAnyHandle> classificationReference in spaceOccupantInfo.ClassificationReferences)
                            {
                                IFCAnyHandle relAssociates = IFCInstanceExporter.CreateRelAssociatesClassification(file, ExporterIFCUtils.CreateGUID(),
                                    exporterIFC.GetOwnerHistoryHandle(), classificationReference.Key, "", spaceOccupantHandles, classificationReference.Value);
                            }

                            if (spaceOccupantInfo.SpaceOccupantProperySetHandle != null && spaceOccupantInfo.SpaceOccupantProperySetHandle.HasValue)
                            {
                                IFCAnyHandle relHnd = IFCInstanceExporter.CreateRelDefinesByProperties(file, ExporterIFCUtils.CreateGUID(),
                                    exporterIFC.GetOwnerHistoryHandle(), null, null, spaceOccupantHandles, spaceOccupantInfo.SpaceOccupantProperySetHandle);
                            }
                        }
                    }
                }

                ExporterIFCUtils.EndExportInternal(exporterIFC);

                //create header

                ExportOptionsCache exportOptionsCache = ExporterCacheManager.ExportOptionsCache;

                string coordinationView = null;
                if (exportOptionsCache.ExportAs2x3CoordinationView2)
                    coordinationView = "CoordinationView_V2.0";
                else
                    coordinationView = "CoordinationView";

                List<string> descriptions = new List<string>();
                if (exportOptionsCache.ExportAs2x2 || ExporterUtil.DoCodeChecking(exportOptionsCache))
                {
                    descriptions.Add("IFC2X_PLATFORM");
                }
                else
                {
                    string currentLine;
                    currentLine = string.Format("ViewDefinition [{0}{1}]",
                       coordinationView,
                       exportOptionsCache.ExportBaseQuantities ? ", QuantityTakeOffAddOnView" : "");

                    descriptions.Add(currentLine);
                }

                string projectNumber = projectInfo.Number;
                string projectName = projectInfo.Name;
                string projectStatus = projectInfo.Status;

                if (projectNumber == null)
                    projectNumber = string.Empty;
                if (projectName == null)
                    projectName = exportOptionsCache.FileName;
                if (projectStatus == null)
                    projectStatus = string.Empty;

                IFCAnyHandle project = exporterIFC.GetProject();
                if (!IFCAnyHandleUtil.IsNullOrHasNoValue(project))
                    IFCAnyHandleUtil.UpdateProject(project, projectNumber, projectName, projectStatus);

                List<string> author = new List<string>();
                author.Add(string.Empty);
                List<string> orginization = new List<string>();
                orginization.Add(string.Empty);
                IFCInstanceExporter.CreateFileSchema(file);
                IFCInstanceExporter.CreateFileDescription(file, descriptions);
                IFCInstanceExporter.CreateFileName(file, projectNumber, author, orginization, document.Application.VersionName,
                    document.Application.VersionBuild, string.Empty);

                transaction.Commit();

                IFCFileWriteOptions writeOptions = new IFCFileWriteOptions();
                writeOptions.FileName = exportOptionsCache.FileName;
                writeOptions.FileFormat = exportOptionsCache.IFCFileFormat;
                if (writeOptions.FileFormat == IFCFileFormat.IfcXML || writeOptions.FileFormat == IFCFileFormat.IfcXMLZIP)
                {
                    writeOptions.XMLConfigFileName = Path.Combine(ExporterUtil.RevitProgramPath, "EDM\\ifcXMLconfiguration.xml");
                }
                file.Write(writeOptions);
            }
        }
예제 #3
0
        /// <summary>
        /// Completes the export process by writing information stored incrementally during export to the file.
        /// </summary>
        /// <param name="exporterIFC">The IFC exporter object.</param>
        /// <param name="document">The document to export.</param>
        private void EndExport(ExporterIFC exporterIFC, Document document)
        {
            IFCFile file = exporterIFC.GetFile();
            using (IFCTransaction transaction = new IFCTransaction(file))
            {
                foreach (KeyValuePair<ElementId, StairRampContainerInfo> stairRamp in ExporterCacheManager.StairRampContainerInfoCache)
                {
                    StairRampContainerInfo stairRampInfo = stairRamp.Value;

                    IList<IFCAnyHandle> hnds = stairRampInfo.StairOrRampHandles;
                    for (int ii = 0; ii < hnds.Count; ii++)
                    {
                        IFCAnyHandle hnd = hnds[ii];
                        if (IFCAnyHandleUtil.IsNullOrHasNoValue(hnd))
                            continue;

                        IList<IFCAnyHandle> comps = stairRampInfo.Components[ii];
                        if (comps.Count == 0)
                            continue;

                        Element elem = document.GetElement(stairRamp.Key);
                        string guid = ExporterIFCUtils.CreateSubElementGUID(elem, (int)IFCStairSubElements.ContainmentRelation);
                        ExporterUtil.RelateObjects(exporterIFC, guid, hnd, comps);
                    }
                }

                ProjectInfo projectInfo = document.ProjectInformation;
                IFCAnyHandle buildingHnd = exporterIFC.GetBuilding();

                // relate assembly elements to assemblies
                foreach (KeyValuePair<ElementId, AssemblyInstanceInfo> assemblyInfoEntry in ExporterCacheManager.AssemblyInstanceCache)
                {
                    AssemblyInstanceInfo assemblyInfo = assemblyInfoEntry.Value;
                    if (assemblyInfo == null)
                        continue;

                    if (assemblyInfo.AssemblyInstanceHandle != null && assemblyInfo.ElementHandles != null &&
                        assemblyInfo.ElementHandles.Count != 0)
                    {
                        Element assemblyInstance = document.GetElement(assemblyInfoEntry.Key);
                        string guid = ExporterIFCUtils.CreateSubElementGUID(assemblyInstance, (int)IFCAssemblyInstanceSubElements.RelContainedInSpatialStructure);
                        ExporterUtil.RelateObjects(exporterIFC, guid, assemblyInfo.AssemblyInstanceHandle, assemblyInfo.ElementHandles);

                        // Set the PlacementRelTo of assembly elements to assembly instance.
                        IFCAnyHandle assemblyPlacement = IFCAnyHandleUtil.GetObjectPlacement(assemblyInfo.AssemblyInstanceHandle);
                        foreach (IFCAnyHandle elementHandle in assemblyInfo.ElementHandles)
                        {
                            // NOTE: caution that old IFCAXIS2PLACEMENT3D will be unused as the new one replace it. 
                            //       But we cannot delete it safely yet because we don't know if any handle is referencing it.
                            IFCAnyHandle elementPlacement = IFCAnyHandleUtil.GetObjectPlacement(elementHandle);
                            Transform relTrf = ExporterIFCUtils.GetRelativeLocalPlacementOffsetTransform(assemblyPlacement, elementPlacement);
                            Transform inverseTrf = relTrf.Inverse;
                            IFCAnyHandle relLocalPlacement = ExporterUtil.CreateAxis2Placement3D(file, inverseTrf.Origin, inverseTrf.BasisZ, inverseTrf.BasisX);
                            IFCAnyHandleUtil.SetAttribute(elementPlacement, "PlacementRelTo", assemblyPlacement);
                            GeometryUtil.SetRelativePlacement(elementPlacement, relLocalPlacement);
                        }
                    }                  
                }

                // create spatial structure holder
                ICollection<IFCAnyHandle> relatedElements = exporterIFC.GetRelatedElements();
                if (relatedElements.Count > 0)
                {
                    HashSet<IFCAnyHandle> relatedElementSet = new HashSet<IFCAnyHandle>(relatedElements);
                    IFCInstanceExporter.CreateRelContainedInSpatialStructure(file,
                        ExporterIFCUtils.CreateSubElementGUID(projectInfo, (int)IFCBuildingSubElements.RelContainedInSpatialStructure),
                        exporterIFC.GetOwnerHistoryHandle(), null, null, relatedElementSet, buildingHnd);
                }

                ICollection<IFCAnyHandle> relatedProducts = exporterIFC.GetRelatedProducts();
                if (relatedProducts.Count > 0)
                {
                    string guid = ExporterIFCUtils.CreateSubElementGUID(projectInfo, (int)IFCBuildingSubElements.RelAggregatesProducts);
                    ExporterCacheManager.ContainmentCache.SetGUIDForRelation(buildingHnd, guid);
                    ExporterCacheManager.ContainmentCache.AddRelations(buildingHnd, relatedProducts);
                }

                // create a default site if we have latitude and longitude information.
                if (IFCAnyHandleUtil.IsNullOrHasNoValue(exporterIFC.GetSite()))
                {
                    using (ProductWrapper productWrapper = ProductWrapper.Create(exporterIFC, true))
                    {
                        SiteExporter.ExportDefaultSite(exporterIFC, document, productWrapper);
                    }
                }

                IFCAnyHandle siteHandle = exporterIFC.GetSite();
                if (!IFCAnyHandleUtil.IsNullOrHasNoValue(siteHandle))
                {
                    ExporterCacheManager.ContainmentCache.AddRelation(exporterIFC.GetProject(), siteHandle);

                    // assoc. site to the building.
                    ExporterCacheManager.ContainmentCache.AddRelation(siteHandle, buildingHnd);

                    ExporterUtil.UpdateBuildingPlacement(buildingHnd, siteHandle);
                }
                else
                {
                    // relate building and project if no site
                    ExporterCacheManager.ContainmentCache.AddRelation(exporterIFC.GetProject(), buildingHnd);
                }

                // relate levels and products.
                RelateLevels(exporterIFC, document);

                // relate objects in containment cache.
                foreach (KeyValuePair<IFCAnyHandle, ICollection<IFCAnyHandle>> container in ExporterCacheManager.ContainmentCache)
                {
                    if (container.Value.Count() > 0)
                    {
                        string relationGUID = ExporterCacheManager.ContainmentCache.GetGUIDForRelation(container.Key);
                        ExporterUtil.RelateObjects(exporterIFC, relationGUID, container.Key, container.Value);
                    }
                }

                // These elements are created internally, but we allow custom property sets for them.  Create them here.
                using (ProductWrapper productWrapper = ProductWrapper.Create(exporterIFC, true))
                {
                    productWrapper.AddBuilding(buildingHnd);
                    ExportElementProperties(exporterIFC, document.ProjectInformation, productWrapper);
                    PropertyUtil.CreateInternalRevitPropertySets(exporterIFC, document.ProjectInformation, productWrapper);
                }

                // create material layer associations
                foreach (IFCAnyHandle materialSetLayerUsageHnd in ExporterCacheManager.MaterialLayerRelationsCache.Keys)
                {
                    IFCInstanceExporter.CreateRelAssociatesMaterial(file, GUIDUtil.CreateGUID(), exporterIFC.GetOwnerHistoryHandle(),
                        null, null, ExporterCacheManager.MaterialLayerRelationsCache[materialSetLayerUsageHnd],
                        materialSetLayerUsageHnd);
                }

                // create material associations
                foreach (IFCAnyHandle materialHnd in ExporterCacheManager.MaterialRelationsCache.Keys)
                {
                    IFCInstanceExporter.CreateRelAssociatesMaterial(file, GUIDUtil.CreateGUID(), exporterIFC.GetOwnerHistoryHandle(),
                        null, null, ExporterCacheManager.MaterialRelationsCache[materialHnd], materialHnd);
                }

                // create type relations
                foreach (IFCAnyHandle typeObj in ExporterCacheManager.TypeRelationsCache.Keys)
                {
                    IFCInstanceExporter.CreateRelDefinesByType(file, GUIDUtil.CreateGUID(), exporterIFC.GetOwnerHistoryHandle(),
                        null, null, ExporterCacheManager.TypeRelationsCache[typeObj], typeObj);
                }

                // create type property relations
                foreach (TypePropertyInfo typePropertyInfo in ExporterCacheManager.TypePropertyInfoCache.Values)
                {
                    ICollection<IFCAnyHandle> propertySets = typePropertyInfo.PropertySets;
                    ICollection<IFCAnyHandle> elements = typePropertyInfo.Elements;

                    if (elements.Count == 0)
                        continue;

                    foreach (IFCAnyHandle propertySet in propertySets)
                    {
                        IFCInstanceExporter.CreateRelDefinesByProperties(file, GUIDUtil.CreateGUID(), exporterIFC.GetOwnerHistoryHandle(),
                            null, null, elements, propertySet);
                    }
                }

                // create space boundaries
                foreach (SpaceBoundary boundary in ExporterCacheManager.SpaceBoundaryCache)
                {
                    SpatialElementExporter.ProcessIFCSpaceBoundary(exporterIFC, boundary, file);
                }

                // create wall/wall connectivity objects
                if (ExporterCacheManager.WallConnectionDataCache.Count > 0)
                {
                    IList<IDictionary<ElementId, IFCAnyHandle>> hostObjects = exporterIFC.GetHostObjects();
                    List<int> relatingPriorities = new List<int>();
                    List<int> relatedPriorities = new List<int>();

                    foreach (WallConnectionData wallConnectionData in ExporterCacheManager.WallConnectionDataCache)
                    {
                        foreach (IDictionary<ElementId, IFCAnyHandle> mapForLevel in hostObjects)
                        {
                            IFCAnyHandle wallElementHandle, otherElementHandle;
                            if (!mapForLevel.TryGetValue(wallConnectionData.FirstId, out wallElementHandle))
                                continue;
                            if (!mapForLevel.TryGetValue(wallConnectionData.SecondId, out otherElementHandle))
                                continue;

                            // NOTE: Definition of RelConnectsPathElements has the connection information reversed
                            // with respect to the order of the paths.
                            IFCInstanceExporter.CreateRelConnectsPathElements(file, GUIDUtil.CreateGUID(), exporterIFC.GetOwnerHistoryHandle(),
                                null, null, wallConnectionData.ConnectionGeometry, wallElementHandle, otherElementHandle, relatingPriorities,
                                relatedPriorities, wallConnectionData.SecondConnectionType, wallConnectionData.FirstConnectionType);
                        }
                    }
                }

                // create Zones
                {
                    string relAssignsToGroupName = "Spatial Zone Assignment";
                    foreach (string zoneName in ExporterCacheManager.ZoneInfoCache.Keys)
                    {
                        ZoneInfo zoneInfo = ExporterCacheManager.ZoneInfoCache.Find(zoneName);
                        if (zoneInfo != null)
                        {
                            IFCAnyHandle zoneHandle = IFCInstanceExporter.CreateZone(file, GUIDUtil.CreateGUID(), exporterIFC.GetOwnerHistoryHandle(),
                                zoneName, zoneInfo.Description, zoneInfo.ObjectType);
                            IFCInstanceExporter.CreateRelAssignsToGroup(file, GUIDUtil.CreateGUID(), exporterIFC.GetOwnerHistoryHandle(),
                                relAssignsToGroupName, null, zoneInfo.RoomHandles, null, zoneHandle);

                            HashSet<IFCAnyHandle> zoneHnds = new HashSet<IFCAnyHandle>();
                            zoneHnds.Add(zoneHandle);

                            foreach (KeyValuePair<string, IFCAnyHandle> classificationReference in zoneInfo.ClassificationReferences)
                            {
                                IFCAnyHandle relAssociates = IFCInstanceExporter.CreateRelAssociatesClassification(file, GUIDUtil.CreateGUID(),
                                    exporterIFC.GetOwnerHistoryHandle(), classificationReference.Key, "", zoneHnds, classificationReference.Value);
                            }

                            if (zoneInfo.EnergyAnalysisProperySetHandle != null && zoneInfo.EnergyAnalysisProperySetHandle.HasValue)
                            {
                                IFCAnyHandle relHnd = IFCInstanceExporter.CreateRelDefinesByProperties(file, GUIDUtil.CreateGUID(),
                                    exporterIFC.GetOwnerHistoryHandle(), null, null, zoneHnds, zoneInfo.EnergyAnalysisProperySetHandle);
                            }

                        }
                    }
                }

                // create Space Occupants
                {
                    foreach (string spaceOccupantName in ExporterCacheManager.SpaceOccupantInfoCache.Keys)
                    {
                        SpaceOccupantInfo spaceOccupantInfo = ExporterCacheManager.SpaceOccupantInfoCache.Find(spaceOccupantName);
                        if (spaceOccupantInfo != null)
                        {
                            IFCAnyHandle person = IFCInstanceExporter.CreatePerson(file, null, spaceOccupantName, null, null, null, null, null, null);
                            IFCAnyHandle spaceOccupantHandle = IFCInstanceExporter.CreateOccupant(file, GUIDUtil.CreateGUID(),
                                exporterIFC.GetOwnerHistoryHandle(), null, null, spaceOccupantName, person, IFCOccupantType.NotDefined);
                            IFCInstanceExporter.CreateRelOccupiesSpaces(file, GUIDUtil.CreateGUID(), exporterIFC.GetOwnerHistoryHandle(),
                                null, null, spaceOccupantInfo.RoomHandles, null, spaceOccupantHandle, null);

                            HashSet<IFCAnyHandle> spaceOccupantHandles = new HashSet<IFCAnyHandle>();
                            spaceOccupantHandles.Add(spaceOccupantHandle);

                            foreach (KeyValuePair<string, IFCAnyHandle> classificationReference in spaceOccupantInfo.ClassificationReferences)
                            {
                                IFCAnyHandle relAssociates = IFCInstanceExporter.CreateRelAssociatesClassification(file, GUIDUtil.CreateGUID(),
                                    exporterIFC.GetOwnerHistoryHandle(), classificationReference.Key, "", spaceOccupantHandles, classificationReference.Value);
                            }

                            if (spaceOccupantInfo.SpaceOccupantProperySetHandle != null && spaceOccupantInfo.SpaceOccupantProperySetHandle.HasValue)
                            {
                                IFCAnyHandle relHnd = IFCInstanceExporter.CreateRelDefinesByProperties(file, GUIDUtil.CreateGUID(),
                                    exporterIFC.GetOwnerHistoryHandle(), null, null, spaceOccupantHandles, spaceOccupantInfo.SpaceOccupantProperySetHandle);
                            }
                        }
                    }
                }

                // Create systems.
                HashSet<IFCAnyHandle> relatedBuildings = new HashSet<IFCAnyHandle>();
                relatedBuildings.Add(buildingHnd);

                foreach (KeyValuePair<ElementId, ICollection<IFCAnyHandle>> system in ExporterCacheManager.SystemsCache.BuiltInSystemsCache)
                {
                    MEPSystem systemElem = document.GetElement(system.Key) as MEPSystem;
                    if (systemElem == null)
                        continue;

                    string desc = "";

                    ElementType systemElemType = document.GetElement(systemElem.GetTypeId()) as ElementType;
                    string objectType = (systemElemType != null) ? systemElemType.Name : "";

                    IFCAnyHandle systemHandle = IFCInstanceExporter.CreateSystem(file, GUIDUtil.CreateGUID(systemElem),
                        exporterIFC.GetOwnerHistoryHandle(), systemElem.Name, desc, objectType);
                    ICollection<IFCAnyHandle> systemHandles = new List<IFCAnyHandle>();
                    systemHandles.Add(systemHandle);
                    PropertyUtil.CreateInternalRevitPropertySets(exporterIFC, systemElem, systemHandles);

                    IFCAnyHandle relServicesBuildings = IFCInstanceExporter.CreateRelServicesBuildings(file, GUIDUtil.CreateGUID(),
                        exporterIFC.GetOwnerHistoryHandle(), null, null, systemHandle, relatedBuildings);

                    IFCAnyHandle relAssignsToGroup = IFCInstanceExporter.CreateRelAssignsToGroup(file, GUIDUtil.CreateGUID(),
                        exporterIFC.GetOwnerHistoryHandle(), null, null, system.Value, IFCObjectType.Product, systemHandle);
                }

                // Add presentation layer assignments - this is in addition to those added in EndExportInternal, and will
                // eventually replace the internal routine.
                foreach (KeyValuePair<string, ICollection<IFCAnyHandle>> presentationLayerSet in ExporterCacheManager.PresentationLayerSetCache)
                {
                    ICollection<IFCAnyHandle> validHandles = new List<IFCAnyHandle>();
                    foreach (IFCAnyHandle handle in presentationLayerSet.Value)
                    {
                        if (!IFCAnyHandleUtil.IsNullOrHasNoValue(handle))
                            validHandles.Add(handle);
                    }

                    if (validHandles.Count > 0)
                        IFCInstanceExporter.CreatePresentationLayerAssignment(file, presentationLayerSet.Key, null, validHandles, null);
                }

                ExporterIFCUtils.EndExportInternal(exporterIFC);

                //create header

                ExportOptionsCache exportOptionsCache = ExporterCacheManager.ExportOptionsCache;

                string coordinationView = null;
                if (exportOptionsCache.ExportAs2x3CoordinationView2)
                    coordinationView = "CoordinationView_V2.0";
                else
                    coordinationView = "CoordinationView";

                List<string> descriptions = new List<string>();
                if (exportOptionsCache.ExportAs2x2 || ExporterUtil.DoCodeChecking(exportOptionsCache))
                {
                    descriptions.Add("IFC2X_PLATFORM");
                }
                else
                {
                    string currentLine;
                    if (String.Compare(exportOptionsCache.SelectedConfigName, "FMHandOverView") == 0)
                    {
                        currentLine = string.Format("ViewDefinition [{0}{1}{2}{3}]",
                           coordinationView,
                           exportOptionsCache.ExportBaseQuantities ? ", QuantityTakeOffAddOnView" : "",
                           ", ", exportOptionsCache.SelectedConfigName);
                    }
                    else
                    {
                        currentLine = string.Format("ViewDefinition [{0}{1}]",
                           coordinationView,
                           exportOptionsCache.ExportBaseQuantities ? ", QuantityTakeOffAddOnView" : "");
                    }

                    descriptions.Add(currentLine);
                  
                }

                string projectNumber = projectInfo.Number;
                string projectName = projectInfo.Name;
                string projectStatus = projectInfo.Status;

                if (projectNumber == null)
                    projectNumber = string.Empty;
                if (projectName == null)
                    projectName = exportOptionsCache.FileName;
                if (projectStatus == null)
                    projectStatus = string.Empty;

                IFCAnyHandle project = exporterIFC.GetProject();
                if (!IFCAnyHandleUtil.IsNullOrHasNoValue(project))
                    IFCAnyHandleUtil.UpdateProject(project, projectNumber, projectName, projectStatus);

                IFCInstanceExporter.CreateFileSchema(file);
                IFCInstanceExporter.CreateFileDescription(file, descriptions);
                // Get stored File Header information from the UI and use it for export
                IFCFileHeader fHeader = new IFCFileHeader();
                IFCFileHeaderItem fHItem = null;

                fHeader.GetSavedFileHeader(document, out fHItem);

                List<string> author = new List<string>();
                if (String.IsNullOrEmpty(fHItem.AuthorName) == false)
                {
                    author.Add(fHItem.AuthorName);
                    if (String.IsNullOrEmpty(fHItem.AuthorEmail) == false)
                        author.Add(fHItem.AuthorEmail);
                }
                else
                    author.Add(String.Empty);

                List<string> organization = new List<string>();
                if (String.IsNullOrEmpty(fHItem.Organization) == false)
                    organization.Add(fHItem.Organization);
                else
                    organization.Add(String.Empty);

                string versionInfos = document.Application.VersionBuild + " - " + ExporterCacheManager.ExportOptionsCache.ExporterVersion + " - " + ExporterCacheManager.ExportOptionsCache.ExporterUIVersion;

                IFCInstanceExporter.CreateFileName(file, projectNumber, author, organization, document.Application.VersionName,
                    versionInfos, fHItem.Authorization);

                transaction.Commit();

                IFCFileWriteOptions writeOptions = new IFCFileWriteOptions();
                writeOptions.FileName = exportOptionsCache.FileName;
                writeOptions.FileFormat = exportOptionsCache.IFCFileFormat;
                if (writeOptions.FileFormat == IFCFileFormat.IfcXML || writeOptions.FileFormat == IFCFileFormat.IfcXMLZIP)
                {
                    writeOptions.XMLConfigFileName = Path.Combine(ExporterUtil.RevitProgramPath, "EDM\\ifcXMLconfiguration.xml");
                }
                file.Write(writeOptions);
            }
        }
예제 #4
0
        /// <summary>
        /// Completes the export process by writing information stored incrementally during export to the file.
        /// </summary>
        /// <param name="exporterIFC">The IFC exporter object.</param>
        /// <param name="document">The document to export.</param>
        private void EndExport(ExporterIFC exporterIFC, Document document)
        {
            IFCFile file = exporterIFC.GetFile();
            IFCAnyHandle ownerHistory = ExporterCacheManager.OwnerHistoryHandle;

            using (IFCTransaction transaction = new IFCTransaction(file))
            {
                // In some cases, like multi-story stairs and ramps, we may have the same Pset used for multiple levels.
                // If ifcParams is null, re-use the property set.
                ISet<string> locallyUsedGUIDs = new HashSet<string>();

                // Relate Ducts and Pipes to their coverings (insulations and linings)
                foreach (ElementId ductOrPipeId in ExporterCacheManager.MEPCache.CoveredElementsCache)
                {
                    IFCAnyHandle ductOrPipeHandle = ExporterCacheManager.MEPCache.Find(ductOrPipeId);
                    if (IFCAnyHandleUtil.IsNullOrHasNoValue(ductOrPipeHandle))
                        continue;

                    HashSet<IFCAnyHandle> coveringHandles = new HashSet<IFCAnyHandle>();

                    try
                    {
                        ICollection<ElementId> liningIds = InsulationLiningBase.GetLiningIds(document, ductOrPipeId);
                        GetElementHandles(liningIds, coveringHandles);
                    }
                    catch
                    {
                    }

                    try
                    {
                        ICollection<ElementId> insulationIds = InsulationLiningBase.GetInsulationIds(document, ductOrPipeId);
                        GetElementHandles(insulationIds, coveringHandles);
                    }
                    catch
                    {
                    }

                    if (coveringHandles.Count > 0)
                        IFCInstanceExporter.CreateRelCoversBldgElements(file, GUIDUtil.CreateGUID(), ownerHistory, null, null, ductOrPipeHandle, coveringHandles);
                }

                // Relate stair components to stairs
                foreach (KeyValuePair<ElementId, StairRampContainerInfo> stairRamp in ExporterCacheManager.StairRampContainerInfoCache)
                {
                    StairRampContainerInfo stairRampInfo = stairRamp.Value;

                    IList<IFCAnyHandle> hnds = stairRampInfo.StairOrRampHandles;
                    for (int ii = 0; ii < hnds.Count; ii++)
                    {
                        IFCAnyHandle hnd = hnds[ii];
                        if (IFCAnyHandleUtil.IsNullOrHasNoValue(hnd))
                            continue;

                        IList<IFCAnyHandle> comps = stairRampInfo.Components[ii];
                        if (comps.Count == 0)
                            continue;

                        Element elem = document.GetElement(stairRamp.Key);
                        string guid = GUIDUtil.CreateSubElementGUID(elem, (int)IFCStairSubElements.ContainmentRelation);
                        if (locallyUsedGUIDs.Contains(guid))
                            guid = GUIDUtil.CreateGUID();
                        else
                            locallyUsedGUIDs.Add(guid);

                        ExporterUtil.RelateObjects(exporterIFC, guid, hnd, comps);
                    }
                }

                ProjectInfo projectInfo = document.ProjectInformation;
                IFCAnyHandle buildingHnd = ExporterCacheManager.BuildingHandle;

                // relate assembly elements to assemblies
                foreach (KeyValuePair<ElementId, AssemblyInstanceInfo> assemblyInfoEntry in ExporterCacheManager.AssemblyInstanceCache)
                {
                    AssemblyInstanceInfo assemblyInfo = assemblyInfoEntry.Value;
                    if (assemblyInfo == null)
                        continue;

                    IFCAnyHandle assemblyInstanceHandle = assemblyInfo.AssemblyInstanceHandle;
                    HashSet<IFCAnyHandle> elementHandles = assemblyInfo.ElementHandles;
                    if (elementHandles != null && assemblyInstanceHandle != null && elementHandles.Contains(assemblyInstanceHandle))
                        elementHandles.Remove(assemblyInstanceHandle);

                    if (assemblyInstanceHandle != null && elementHandles != null && elementHandles.Count != 0)
                    {
                        Element assemblyInstance = document.GetElement(assemblyInfoEntry.Key);
                        string guid = GUIDUtil.CreateSubElementGUID(assemblyInstance, (int)IFCAssemblyInstanceSubElements.RelContainedInSpatialStructure);

                        if (IFCAnyHandleUtil.IsSubTypeOf(assemblyInstanceHandle, IFCEntityType.IfcSystem))
                        {
                            IFCInstanceExporter.CreateRelAssignsToGroup(file, guid, ownerHistory, null, null, elementHandles, null, assemblyInstanceHandle);
                        }
                        else
                        {
                            ExporterUtil.RelateObjects(exporterIFC, guid, assemblyInstanceHandle, elementHandles);
                            // Set the PlacementRelTo of assembly elements to assembly instance.
                            IFCAnyHandle assemblyPlacement = IFCAnyHandleUtil.GetObjectPlacement(assemblyInstanceHandle);
                            AssemblyInstanceExporter.SetLocalPlacementsRelativeToAssembly(exporterIFC, assemblyPlacement, elementHandles);
                        }

                        // We don't do this in RegisterAssemblyElement because we want to make sure that the IfcElementAssembly has been created.
                        ExporterCacheManager.ElementsInAssembliesCache.UnionWith(elementHandles);
                    }
                }

                // relate group elements to groups
                foreach (KeyValuePair<ElementId, GroupInfo> groupEntry in ExporterCacheManager.GroupCache)
                {
                    GroupInfo groupInfo = groupEntry.Value;
                    if (groupInfo == null)
                        continue;

                    if (groupInfo.GroupHandle != null && groupInfo.ElementHandles != null &&
                        groupInfo.ElementHandles.Count != 0)
                    {
                        Element group = document.GetElement(groupEntry.Key);
                        string guid = GUIDUtil.CreateSubElementGUID(group, (int)IFCGroupSubElements.RelAssignsToGroup);

                        IFCAnyHandle groupHandle = groupInfo.GroupHandle;
                        HashSet<IFCAnyHandle> elementHandles = groupInfo.ElementHandles;
                        if (elementHandles != null && groupHandle != null && elementHandles.Contains(groupHandle))
                            elementHandles.Remove(groupHandle);

                        if (elementHandles != null && groupHandle != null && elementHandles.Count > 0)
                        {
                            IFCInstanceExporter.CreateRelAssignsToGroup(file, guid, ownerHistory, null, null, elementHandles, null, groupHandle);
                        }
                    }
                }

            // create an association between the IfcBuilding and building elements with no other containment.
            HashSet<IFCAnyHandle> buildingElements = RemoveContainedHandlesFromSet(ExporterCacheManager.LevelInfoCache.OrphanedElements);
            buildingElements.UnionWith(exporterIFC.GetRelatedElements());
            if (buildingElements.Count > 0)
                {
               HashSet<IFCAnyHandle> relatedElementSet = new HashSet<IFCAnyHandle>(buildingElements);
                    string guid = GUIDUtil.CreateSubElementGUID(projectInfo, (int)IFCBuildingSubElements.RelContainedInSpatialStructure);
                    IFCInstanceExporter.CreateRelContainedInSpatialStructure(file, guid,
                        ownerHistory, null, null, relatedElementSet, buildingHnd);
                }

            // create an association between the IfcBuilding and spacial elements with no other containment.
            // The name "GetRelatedProducts()" is misleading; this only covers spaces.
            HashSet<IFCAnyHandle> buildingSapces = RemoveContainedHandlesFromSet(ExporterCacheManager.LevelInfoCache.OrphanedSpaces);
            buildingSapces.UnionWith(exporterIFC.GetRelatedProducts());
            if (buildingSapces.Count > 0)
                {
                    string guid = GUIDUtil.CreateSubElementGUID(projectInfo, (int)IFCBuildingSubElements.RelAggregatesProducts);
                    ExporterCacheManager.ContainmentCache.SetGUIDForRelation(buildingHnd, guid);
               ExporterCacheManager.ContainmentCache.AddRelations(buildingHnd, buildingSapces);
                }

                // create a default site if we have latitude and longitude information.
                if (IFCAnyHandleUtil.IsNullOrHasNoValue(ExporterCacheManager.SiteHandle))
                {
                    using (ProductWrapper productWrapper = ProductWrapper.Create(exporterIFC, true))
                    {
                        SiteExporter.ExportDefaultSite(exporterIFC, document, productWrapper);
                    }
                }

                IFCAnyHandle siteHandle = ExporterCacheManager.SiteHandle;
                if (!IFCAnyHandleUtil.IsNullOrHasNoValue(siteHandle))
                {
                    ExporterCacheManager.ContainmentCache.AddRelation(ExporterCacheManager.ProjectHandle, siteHandle);

                    // assoc. site to the building.
                    ExporterCacheManager.ContainmentCache.AddRelation(siteHandle, buildingHnd);

                    ExporterUtil.UpdateBuildingRelToPlacement(buildingHnd, siteHandle);
                }
                else
                {
                    // relate building and project if no site
                    ExporterCacheManager.ContainmentCache.AddRelation(ExporterCacheManager.ProjectHandle, buildingHnd);
                }

                // relate levels and products.
                RelateLevels(exporterIFC, document);

                // relate objects in containment cache.
                foreach (KeyValuePair<IFCAnyHandle, ICollection<IFCAnyHandle>> container in ExporterCacheManager.ContainmentCache)
                {
                    if (container.Value.Count() > 0)
                    {
                        string relationGUID = ExporterCacheManager.ContainmentCache.GetGUIDForRelation(container.Key);
                        ExporterUtil.RelateObjects(exporterIFC, relationGUID, container.Key, container.Value);
                    }
                }

                // These elements are created internally, but we allow custom property sets for them.  Create them here.
                using (ProductWrapper productWrapper = ProductWrapper.Create(exporterIFC, true))
                {
                    productWrapper.AddBuilding(projectInfo, buildingHnd);
                    if (projectInfo != null)
                        ExporterUtil.ExportRelatedProperties(exporterIFC, projectInfo, productWrapper);
                }

                // create material layer associations
                foreach (IFCAnyHandle materialSetLayerUsageHnd in ExporterCacheManager.MaterialLayerRelationsCache.Keys)
                {
                    IFCInstanceExporter.CreateRelAssociatesMaterial(file, GUIDUtil.CreateGUID(), ownerHistory,
                        null, null, ExporterCacheManager.MaterialLayerRelationsCache[materialSetLayerUsageHnd],
                        materialSetLayerUsageHnd);
                }

                // create material associations
                foreach (IFCAnyHandle materialHnd in ExporterCacheManager.MaterialRelationsCache.Keys)
                {
                    IFCInstanceExporter.CreateRelAssociatesMaterial(file, GUIDUtil.CreateGUID(), ownerHistory,
                        null, null, ExporterCacheManager.MaterialRelationsCache[materialHnd], materialHnd);
                }

                // create type relations
                foreach (IFCAnyHandle typeObj in ExporterCacheManager.TypeRelationsCache.Keys)
                {
                    IFCInstanceExporter.CreateRelDefinesByType(file, GUIDUtil.CreateGUID(), ownerHistory,
                        null, null, ExporterCacheManager.TypeRelationsCache[typeObj], typeObj);
                }

                // create type property relations
                foreach (TypePropertyInfo typePropertyInfo in ExporterCacheManager.TypePropertyInfoCache.Values)
                {
                    if (typePropertyInfo.AssignedToType)
                        continue;

                    ICollection<IFCAnyHandle> propertySets = typePropertyInfo.PropertySets;
                    ISet<IFCAnyHandle> elements = typePropertyInfo.Elements;

                    if (elements.Count == 0)
                        continue;

                    foreach (IFCAnyHandle propertySet in propertySets)
                    {
                        try
                        {
                            ExporterUtil.CreateRelDefinesByProperties(file, GUIDUtil.CreateGUID(), ownerHistory,
                                                            null, null, elements, propertySet);
                        }
                        catch
                        {
                        }
                    }
                }

                // create space boundaries
                foreach (SpaceBoundary boundary in ExporterCacheManager.SpaceBoundaryCache)
                {
                    SpatialElementExporter.ProcessIFCSpaceBoundary(exporterIFC, boundary, file);
                }

                // create wall/wall connectivity objects
                if (ExporterCacheManager.WallConnectionDataCache.Count > 0)
                {
                    IList<IDictionary<ElementId, IFCAnyHandle>> hostObjects = exporterIFC.GetHostObjects();
                    List<int> relatingPriorities = new List<int>();
                    List<int> relatedPriorities = new List<int>();

                    foreach (WallConnectionData wallConnectionData in ExporterCacheManager.WallConnectionDataCache)
                    {
                        foreach (IDictionary<ElementId, IFCAnyHandle> mapForLevel in hostObjects)
                        {
                            IFCAnyHandle wallElementHandle, otherElementHandle;
                            if (!mapForLevel.TryGetValue(wallConnectionData.FirstId, out wallElementHandle))
                                continue;
                            if (!mapForLevel.TryGetValue(wallConnectionData.SecondId, out otherElementHandle))
                                continue;

                            // NOTE: Definition of RelConnectsPathElements has the connection information reversed
                            // with respect to the order of the paths.
                     string connectionName = ExporterUtil.GetGlobalId(wallElementHandle) + "|"
                                                 + ExporterUtil.GetGlobalId(otherElementHandle);
                            string connectionType = "Structural";   // Assigned as Description
                            IFCInstanceExporter.CreateRelConnectsPathElements(file, GUIDUtil.CreateGUID(), ownerHistory,
                                connectionName, connectionType, wallConnectionData.ConnectionGeometry, wallElementHandle, otherElementHandle, relatingPriorities,
                                relatedPriorities, wallConnectionData.SecondConnectionType, wallConnectionData.FirstConnectionType);
                        }
                    }
                }

                // create Zones
                {
                    string relAssignsToGroupName = "Spatial Zone Assignment";
                    foreach (string zoneName in ExporterCacheManager.ZoneInfoCache.Keys)
                    {
                        ZoneInfo zoneInfo = ExporterCacheManager.ZoneInfoCache.Find(zoneName);
                        if (zoneInfo != null)
                        {
                            IFCAnyHandle zoneHandle = IFCInstanceExporter.CreateZone(file, GUIDUtil.CreateGUID(), ownerHistory,
                                zoneName, zoneInfo.Description, zoneInfo.ObjectType);
                            IFCInstanceExporter.CreateRelAssignsToGroup(file, GUIDUtil.CreateGUID(), ownerHistory,
                                relAssignsToGroupName, null, zoneInfo.RoomHandles, null, zoneHandle);

                            HashSet<IFCAnyHandle> zoneHnds = new HashSet<IFCAnyHandle>();
                            zoneHnds.Add(zoneHandle);

                            foreach (KeyValuePair<string, IFCAnyHandle> classificationReference in zoneInfo.ClassificationReferences)
                            {
                                IFCAnyHandle relAssociates = IFCInstanceExporter.CreateRelAssociatesClassification(file, GUIDUtil.CreateGUID(),
                                    ownerHistory, classificationReference.Key, "", zoneHnds, classificationReference.Value);
                            }

                            if (!IFCAnyHandleUtil.IsNullOrHasNoValue(zoneInfo.EnergyAnalysisProperySetHandle))
                            {
                                ExporterUtil.CreateRelDefinesByProperties(file, GUIDUtil.CreateGUID(),
                                                                    ownerHistory, null, null, zoneHnds, zoneInfo.EnergyAnalysisProperySetHandle);
                            }

                            if (!IFCAnyHandleUtil.IsNullOrHasNoValue(zoneInfo.ZoneCommonProperySetHandle))
                            {
                                ExporterUtil.CreateRelDefinesByProperties(file, GUIDUtil.CreateGUID(),
                                    ownerHistory, null, null, zoneHnds, zoneInfo.ZoneCommonProperySetHandle);
                            }
                        }
                    }
                }

                // create Space Occupants
                {
                    foreach (string spaceOccupantName in ExporterCacheManager.SpaceOccupantInfoCache.Keys)
                    {
                        SpaceOccupantInfo spaceOccupantInfo = ExporterCacheManager.SpaceOccupantInfoCache.Find(spaceOccupantName);
                        if (spaceOccupantInfo != null)
                        {
                            IFCAnyHandle person = IFCInstanceExporter.CreatePerson(file, null, spaceOccupantName, null, null, null, null, null, null);
                            IFCAnyHandle spaceOccupantHandle = IFCInstanceExporter.CreateOccupant(file, GUIDUtil.CreateGUID(),
                                ownerHistory, null, null, spaceOccupantName, person, IFCOccupantType.NotDefined);
                            IFCInstanceExporter.CreateRelOccupiesSpaces(file, GUIDUtil.CreateGUID(), ownerHistory,
                                null, null, spaceOccupantInfo.RoomHandles, null, spaceOccupantHandle, null);

                            HashSet<IFCAnyHandle> spaceOccupantHandles = new HashSet<IFCAnyHandle>();
                            spaceOccupantHandles.Add(spaceOccupantHandle);

                            foreach (KeyValuePair<string, IFCAnyHandle> classificationReference in spaceOccupantInfo.ClassificationReferences)
                            {
                                IFCAnyHandle relAssociates = IFCInstanceExporter.CreateRelAssociatesClassification(file, GUIDUtil.CreateGUID(),
                                    ownerHistory, classificationReference.Key, "", spaceOccupantHandles, classificationReference.Value);
                            }

                            if (spaceOccupantInfo.SpaceOccupantProperySetHandle != null && spaceOccupantInfo.SpaceOccupantProperySetHandle.HasValue)
                            {
                                ExporterUtil.CreateRelDefinesByProperties(file, GUIDUtil.CreateGUID(),
                                                                  ownerHistory, null, null, spaceOccupantHandles, spaceOccupantInfo.SpaceOccupantProperySetHandle);
                            }
                        }
                    }
                }

                // Create systems.
                HashSet<IFCAnyHandle> relatedBuildings = new HashSet<IFCAnyHandle>();
                relatedBuildings.Add(buildingHnd);

                using (ProductWrapper productWrapper = ProductWrapper.Create(exporterIFC, true))
                {
                    foreach (KeyValuePair<ElementId, ISet<IFCAnyHandle>> system in ExporterCacheManager.SystemsCache.BuiltInSystemsCache)
                    {
                        MEPSystem systemElem = document.GetElement(system.Key) as MEPSystem;
                        if (systemElem == null)
                            continue;

                        Element baseEquipment = systemElem.BaseEquipment;
                        if (baseEquipment != null)
                        {
                            IFCAnyHandle memberHandle = ExporterCacheManager.MEPCache.Find(baseEquipment.Id);
                            if (!IFCAnyHandleUtil.IsNullOrHasNoValue(memberHandle))
                                system.Value.Add(memberHandle);
                        }

                        ElementType systemElemType = document.GetElement(systemElem.GetTypeId()) as ElementType;
                        string name = NamingUtil.GetNameOverride(systemElem, systemElem.Name);
                        string desc = NamingUtil.GetDescriptionOverride(systemElem, null);
                        string objectType = NamingUtil.GetObjectTypeOverride(systemElem,
                            (systemElemType != null) ? systemElemType.Name : "");

                        string systemGUID = GUIDUtil.CreateGUID(systemElem);
                        IFCAnyHandle systemHandle = IFCInstanceExporter.CreateSystem(file, systemGUID,
                            ownerHistory, name, desc, objectType);

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

                        productWrapper.AddSystem(systemElem, systemHandle);

                        IFCAnyHandle relServicesBuildings = IFCInstanceExporter.CreateRelServicesBuildings(file, GUIDUtil.CreateGUID(),
                            ownerHistory, null, null, systemHandle, relatedBuildings);

                        IFCObjectType? objType = null;
                        if (!ExporterCacheManager.ExportOptionsCache.ExportAsCoordinationView2)
                            objType = IFCObjectType.Product;
                        IFCAnyHandle relAssignsToGroup = IFCInstanceExporter.CreateRelAssignsToGroup(file, GUIDUtil.CreateGUID(),
                            ownerHistory, null, null, system.Value, objType, systemHandle);
                    }
                }

                using (ProductWrapper productWrapper = ProductWrapper.Create(exporterIFC, true))
                {
                    foreach (KeyValuePair<ElementId, ISet<IFCAnyHandle>> entries in ExporterCacheManager.SystemsCache.ElectricalSystemsCache)
                    {
                        ElementId systemId = entries.Key;
                        MEPSystem systemElem = document.GetElement(systemId) as MEPSystem;
                        if (systemElem == null)
                            continue;

                        Element baseEquipment = systemElem.BaseEquipment;
                        if (baseEquipment != null)
                        {
                            IFCAnyHandle memberHandle = ExporterCacheManager.MEPCache.Find(baseEquipment.Id);
                            if (!IFCAnyHandleUtil.IsNullOrHasNoValue(memberHandle))
                                entries.Value.Add(memberHandle);
                        }

                        // The Elements property below can throw an InvalidOperationException in some cases, which could
                        // crash the export.  Protect against this without having too generic a try/catch block.
                        try
                        {
                            ElementSet members = systemElem.Elements;
                            foreach (Element member in members)
                            {
                                IFCAnyHandle memberHandle = ExporterCacheManager.MEPCache.Find(member.Id);
                                if (!IFCAnyHandleUtil.IsNullOrHasNoValue(memberHandle))
                                    entries.Value.Add(memberHandle);
                            }
                        }
                        catch
                        {
                        }

                        if (entries.Value.Count == 0)
                            continue;

                        ElementType systemElemType = document.GetElement(systemElem.GetTypeId()) as ElementType;
                        string name = NamingUtil.GetNameOverride(systemElem, systemElem.Name);
                        string desc = NamingUtil.GetDescriptionOverride(systemElem, null);
                        string objectType = NamingUtil.GetObjectTypeOverride(systemElem,
                            (systemElemType != null) ? systemElemType.Name : "");

                        string systemGUID = GUIDUtil.CreateGUID(systemElem);
                        IFCAnyHandle systemHandle = IFCInstanceExporter.CreateSystem(file,
                            systemGUID, ownerHistory, name, desc, objectType);

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

                        productWrapper.AddSystem(systemElem, systemHandle);

                        IFCAnyHandle relServicesBuildings = IFCInstanceExporter.CreateRelServicesBuildings(file, GUIDUtil.CreateGUID(),
                            ownerHistory, null, null, systemHandle, relatedBuildings);

                        IFCObjectType? objType = null;
                        if (!ExporterCacheManager.ExportOptionsCache.ExportAsCoordinationView2)
                            objType = IFCObjectType.Product;
                        IFCAnyHandle relAssignsToGroup = IFCInstanceExporter.CreateRelAssignsToGroup(file, GUIDUtil.CreateGUID(),
                            ownerHistory, null, null, entries.Value, objType, systemHandle);
                    }
                }

                // Add presentation layer assignments - this is in addition to those added in EndExportInternal, and will
                // eventually replace the internal routine.
                foreach (KeyValuePair<string, ICollection<IFCAnyHandle>> presentationLayerSet in ExporterCacheManager.PresentationLayerSetCache)
                {
                    ISet<IFCAnyHandle> validHandles = new HashSet<IFCAnyHandle>();
                    foreach (IFCAnyHandle handle in presentationLayerSet.Value)
                    {
                        if (!IFCAnyHandleUtil.IsNullOrHasNoValue(handle))
                            validHandles.Add(handle);
                    }

                    if (validHandles.Count > 0)
                        IFCInstanceExporter.CreatePresentationLayerAssignment(file, presentationLayerSet.Key, null, validHandles, null);
                }

                // Add door/window openings.
                ExporterCacheManager.DoorWindowDelayedOpeningCreatorCache.ExecuteCreators(exporterIFC, document);

                foreach (SpaceInfo spaceInfo in ExporterCacheManager.SpaceInfoCache.SpaceInfos.Values)
                {
                    if (spaceInfo.RelatedElements.Count > 0)
                    {
                        IFCInstanceExporter.CreateRelContainedInSpatialStructure(file, GUIDUtil.CreateGUID(), ownerHistory,
                            null, null, spaceInfo.RelatedElements, spaceInfo.SpaceHandle);
                    }
                }

                // Potentially modify elements with GUID values.
                if (ExporterCacheManager.GUIDsToStoreCache.Count > 0 && !ExporterCacheManager.ExportOptionsCache.ExportingLink)
                {
                    using (SubTransaction st = new SubTransaction(document))
                    {
                        st.Start();
                        foreach (KeyValuePair<KeyValuePair<Element, BuiltInParameter>, string> elementAndGUID in ExporterCacheManager.GUIDsToStoreCache)
                        {
                            if (elementAndGUID.Key.Key == null || elementAndGUID.Key.Value == BuiltInParameter.INVALID || elementAndGUID.Value == null)
                                continue;

                            ParameterUtil.SetStringParameter(elementAndGUID.Key.Key, elementAndGUID.Key.Value, elementAndGUID.Value);
                        }
                        st.Commit();
                    }
                }

                // Allow native code to remove some unused handles, assign presentation map information and clear internal caches.
                ExporterIFCUtils.EndExportInternal(exporterIFC);
            transaction.Commit();
         }
      }