/// <summary> /// Export the parts as independent building elements. /// </summary> /// <remarks> /// The function works with AlternateIFCUI and it requires two conditions: /// 1. Allows export parts: 'current view only' is checked and 'show parts' is selected. /// 2. Allows export parts independent: 'Export parts as building elements' is checked in alternate UI dialog. /// </remarks> /// <param name="exporterIFC">The ExporterIFC object.</param> /// <param name="partElement">The standalone part to export.</param> /// <param name="geometryElement">The goemetry of the part.</param> /// <param name="productWrapper">The ProductWrapper object.</param> public static void ExportPartAsBuildingElement(ExporterIFC exporterIFC, Element partElement, GeometryElement geometryElement, ProductWrapper productWrapper) { Part part = partElement as Part; if (!ExporterCacheManager.ExportOptionsCache.ExportParts || part == null || geometryElement == null) { return; } bool isWall = part.OriginalCategoryId == new ElementId(BuiltInCategory.OST_Walls); bool isColumn = part.OriginalCategoryId == new ElementId(BuiltInCategory.OST_Columns); bool isWallOrColumn = isWall || isColumn; IFCExtrusionAxes ifcExtrusionAxes = GetDefaultExtrusionAxesForPart(part); Element hostElement = null; ElementId overrideLevelId = null; // Find the host element of the part. hostElement = FindRootParent(part, part.OriginalCategoryId); // If part's level is not associated, try to get the host's level with the same category. if (hostElement != null) { overrideLevelId = hostElement.LevelId; } // Split parts with original category is wall or column and the option wall or column is split by level is checked, and then export; // otherwise, export separate parts normally. if (isWallOrColumn && ExporterCacheManager.ExportOptionsCache.WallAndColumnSplitting) { IList <ElementId> levels = new List <ElementId>(); IList <IFCRange> ranges = new List <IFCRange>(); IFCExportType exportType = isWall ? IFCExportType.IfcWall : IFCExportType.IfcColumnType; LevelUtil.CreateSplitLevelRangesForElement(exporterIFC, exportType, part, out levels, out ranges); if (ranges.Count == 0) { PartExporter.ExportPart(exporterIFC, partElement, productWrapper, null, null, null, ifcExtrusionAxes, hostElement, overrideLevelId, true); } else { for (int ii = 0; ii < ranges.Count; ii++) { PartExporter.ExportPart(exporterIFC, partElement, productWrapper, null, null, ranges[ii], ifcExtrusionAxes, hostElement, levels[ii], true); } } } else { PartExporter.ExportPart(exporterIFC, partElement, productWrapper, null, null, null, ifcExtrusionAxes, hostElement, overrideLevelId, true); } }
/// <summary> /// Export all the parts of the host element. /// </summary> /// <param name="exporterIFC">The ExporterIFC object.</param> /// <param name="hostElement">The host element having parts to export.</param> /// <param name="hostHandle">The host element handle.</param> /// <param name="originalWrapper">The ProductWrapper object.</param> public static void ExportHostPart(ExporterIFC exporterIFC, Element hostElement, IFCAnyHandle hostHandle, ProductWrapper originalWrapper, PlacementSetter placementSetter, IFCAnyHandle originalPlacement, ElementId overrideLevelId) { using (ProductWrapper subWrapper = ProductWrapper.Create(exporterIFC, true)) { List <ElementId> associatedPartsList = PartUtils.GetAssociatedParts(hostElement.Document, hostElement.Id, false, true).ToList(); if (associatedPartsList.Count == 0) { return; } bool isWallOrColumn = IsHostWallOrColumn(exporterIFC, hostElement); bool hasOverrideLevel = overrideLevelId != null && overrideLevelId != ElementId.InvalidElementId; IFCExtrusionAxes ifcExtrusionAxes = GetDefaultExtrusionAxesForHost(exporterIFC, hostElement); // Split parts if wall or column is split by level, and then export; otherwise, export parts normally. if (isWallOrColumn && hasOverrideLevel && ExporterCacheManager.ExportOptionsCache.WallAndColumnSplitting) { if (!ExporterCacheManager.HostPartsCache.HasRegistered(hostElement.Id)) { SplitParts(exporterIFC, hostElement, associatedPartsList); // Split parts and associate them with host. } // Find and export the parts that are split by specific level. List <KeyValuePair <Part, IFCRange> > splitPartRangeList = new List <KeyValuePair <Part, IFCRange> >(); splitPartRangeList = ExporterCacheManager.HostPartsCache.Find(hostElement.Id, overrideLevelId); foreach (KeyValuePair <Part, IFCRange> partRange in splitPartRangeList) { PartExporter.ExportPart(exporterIFC, partRange.Key, subWrapper, placementSetter, originalPlacement, partRange.Value, ifcExtrusionAxes, hostElement, overrideLevelId, false); } } else { foreach (ElementId partId in associatedPartsList) { Part part = hostElement.Document.GetElement(partId) as Part; PartExporter.ExportPart(exporterIFC, part, subWrapper, placementSetter, originalPlacement, null, ifcExtrusionAxes, hostElement, overrideLevelId, false); } } // Create the relationship of Host and Parts. ICollection <IFCAnyHandle> relatedElementIds = subWrapper.GetAllObjects(); if (relatedElementIds.Count > 0) { string guid = GUIDUtil.CreateGUID(); HashSet <IFCAnyHandle> relatedElementIdSet = new HashSet <IFCAnyHandle>(relatedElementIds); IFCInstanceExporter.CreateRelAggregates(exporterIFC.GetFile(), guid, exporterIFC.GetOwnerHistoryHandle(), null, null, hostHandle, relatedElementIdSet); } } }
/// <summary> /// Export the standalone parts: /// - The parts made from originals in Links /// - The Orphan parts: the linked file where the original host element comes from is unloaded. /// - The Zombie parts: the original host element is deleted from the linked file. /// </summary> /// <remarks> /// This is a temporary workaround to export the parts made from linked elements. It should be refined when linked are supported (LinkedInstance at least.) /// There are some limitations: /// The linked element will not export as host, including the relative elements: e.g. windows, doors, openings. /// The host part cannot export if visibility is set by linked view and has 'Show Original'. /// The standalone part will skip export if Base Level is set 'Non Associated'. /// The linked part export cannot be split even if its category is wall or column and 'Split wall or column by story' is checked. /// </remarks> /// <param name="exporterIFC">The ExporterIFC object.</param> /// <param name="partElement">The standalone part to export.</param> /// <param name="geometryElement">The goemetry of the part.</param> /// <param name="productWrapper">The ProductWrapper object.</param> public static void ExportStandalonePart(ExporterIFC exporterIFC, Element partElement, GeometryElement geometryElement, ProductWrapper productWrapper) { Part part = partElement as Part; if (!ExporterCacheManager.ExportOptionsCache.ExportParts || part == null || geometryElement == null) { return; } if (IsAnyHostElementLocal(part)) { // Has host element, so should export with host element. return; } ElementId overrideLevelId = null; if (part.LevelId == ElementId.InvalidElementId) { // If part's level is not associated, try to get the host's level with the same category. Element hostElement = FindRootParent(part, part.OriginalCategoryId); if (hostElement == null) { return; } overrideLevelId = hostElement.LevelId; if (overrideLevelId == ElementId.InvalidElementId) { return; } } IFCExtrusionAxes ifcExtrusionAxes = GetDefaultExtrusionAxesForPart(part); PartExporter.ExportPart(exporterIFC, partElement, productWrapper, null, null, null, ifcExtrusionAxes, null, overrideLevelId, false); }