/// <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); } } } }
/// <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); } }
/// <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); } }
/// <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(); } }