/// <summary> /// Creates a creator from IFCOpeningData. /// </summary> /// <param name="exporterIFC">The exporter.</param> /// <param name="openingData">The IFCOpeningData.</param> /// <param name="scaledHostWidth">The scaled host width.</param> /// <param name="hostId">The host id.</param> /// <param name="hostHnd">The host handle.</param> /// <param name="levelId">The base level id.</param> /// <returns>The creator.</returns> public static DoorWindowDelayedOpeningCreator Create(ExporterIFC exporterIFC, IFCOpeningData openingData, double scaledHostWidth, ElementId hostId, IFCAnyHandle hostHnd, ElementId levelId) { DoorWindowDelayedOpeningCreator creator = new DoorWindowDelayedOpeningCreator(); creator.InsertId = openingData.OpeningElementId; creator.HostId = hostId; creator.HostHnd = hostHnd; creator.ExtrusionData = openingData.GetExtrusionData(); // We can't be guaranteed that the GetOpeningSolids data won't be stale by the time we are ready // to use it. As such, we will clone the geometry here. IList <Solid> openingSolids = openingData.GetOpeningSolids(); IList <Solid> creatorSolids = new List <Solid>(); foreach (Solid openingSolid in openingSolids) { creatorSolids.Add(SolidUtils.Clone(openingSolid)); } creator.Solids = creatorSolids; creator.IsRecess = openingData.IsRecess; creator.CreatedFromDoorWindowInfo = false; creator.ScaledHostWidth = scaledHostWidth; creator.LevelId = levelId; if ((creator.ExtrusionData != null && creator.ExtrusionData.Count > 0) || (creator.Solids != null && creator.Solids.Count > 0)) { creator.HasValidGeometry = true; } return(creator); }
/// <summary> /// Copies geometries from another creator. /// </summary> /// <param name="otherCreator">The other creator.</param> public void CopyGeometry(DoorWindowDelayedOpeningCreator otherCreator) { ExtrusionData = otherCreator.ExtrusionData; Solids = otherCreator.Solids; IsRecess = otherCreator.IsRecess; ScaledHostWidth = otherCreator.ScaledHostWidth; if ((ExtrusionData != null && ExtrusionData.Count > 0) || (Solids != null && Solids.Count > 0)) { HasValidGeometry = true; } }
/// <summary> /// Copy constructor. /// </summary> /// <param name="orig">The DoorWindowDelayedOpeningCreator.</param> public DoorWindowDelayedOpeningCreator(DoorWindowDelayedOpeningCreator orig) { HasValidGeometry = orig.HasValidGeometry; CreatedFromDoorWindowInfo = orig.CreatedFromDoorWindowInfo; PosHingeSide = orig.PosHingeSide; IsRecess = orig.IsRecess; HostId = orig.HostId; InsertId = orig.InsertId; DoorWindowHnd = orig.DoorWindowHnd; HostHnd = orig.HostHnd; LevelId = orig.LevelId; ExtrusionData = orig.ExtrusionData; Solids = orig.Solids; }
/// <summary> /// Adds a new DoorWindowDelayedOpeningCreator. /// </summary> /// <param name="creator">The creator.</param> public void Add(DoorWindowDelayedOpeningCreator creator) { if (creator == null) { return; } Dictionary <ElementId, DoorWindowDelayedOpeningCreator> existingOpenings = null; if (!m_DelayedOpeningCreators.TryGetValue(creator.InsertId, out existingOpenings)) { existingOpenings = new Dictionary <ElementId, DoorWindowDelayedOpeningCreator>(); m_DelayedOpeningCreators[creator.InsertId] = existingOpenings; } ElementId levelIdToUse = ExporterCacheManager.ExportOptionsCache.WallAndColumnSplitting ? creator.LevelId : ElementId.InvalidElementId; DoorWindowDelayedOpeningCreator oldCreator = null; if (existingOpenings.TryGetValue(levelIdToUse, out oldCreator)) { // from DoorWindowInfo has higher priority if (oldCreator.CreatedFromDoorWindowInfo) { if (!oldCreator.HasValidGeometry && creator.HasValidGeometry) { oldCreator.CopyGeometry(creator); } } else if (creator.CreatedFromDoorWindowInfo) { if (!creator.HasValidGeometry && oldCreator.HasValidGeometry) { creator.CopyGeometry(oldCreator); } existingOpenings[levelIdToUse] = creator; } } else { existingOpenings[levelIdToUse] = creator; } }
/// <summary> /// Creates a creator from IFCOpeningData. /// </summary> /// <param name="exporterIFC">The exporter.</param> /// <param name="openingData">The IFCOpeningData.</param> /// <param name="scaledHostWidth">The scaled host width.</param> /// <param name="hostId">The host id.</param> /// <param name="hostHnd">The host handle.</param> /// <param name="levelId">The base level id.</param> /// <returns>The creator.</returns> public static DoorWindowDelayedOpeningCreator Create(ExporterIFC exporterIFC, IFCOpeningData openingData, double scaledHostWidth, ElementId hostId, IFCAnyHandle hostHnd, ElementId levelId) { DoorWindowDelayedOpeningCreator creator = new DoorWindowDelayedOpeningCreator(); creator.InsertId = openingData.OpeningElementId; creator.HostId = hostId; creator.HostHnd = hostHnd; creator.ExtrusionData = openingData.GetExtrusionData(); creator.Solids = openingData.GetOpeningSolids(); creator.IsRecess = openingData.IsRecess; creator.CreatedFromDoorWindowInfo = false; creator.ScaledHostWidth = scaledHostWidth; creator.LevelId = levelId; if ((creator.ExtrusionData != null && creator.ExtrusionData.Count > 0) || (creator.Solids != null && creator.Solids.Count > 0)) { creator.HasValidGeometry = true; } return(creator); }
/// <summary> /// Adds a new DoorWindowDelayedOpeningCreator. /// </summary> /// <param name="creator">The creator.</param> public void Add(DoorWindowDelayedOpeningCreator creator) { if (creator == null) return; Dictionary<ElementId, DoorWindowDelayedOpeningCreator> existingOpenings = null; if (!m_DelayedOpeningCreators.TryGetValue(creator.InsertId, out existingOpenings)) { existingOpenings = new Dictionary<ElementId, DoorWindowDelayedOpeningCreator>(); m_DelayedOpeningCreators[creator.InsertId] = existingOpenings; } ElementId levelIdToUse = ExporterCacheManager.ExportOptionsCache.WallAndColumnSplitting ? creator.LevelId : ElementId.InvalidElementId; DoorWindowDelayedOpeningCreator oldCreator = null; if (existingOpenings.TryGetValue(levelIdToUse, out oldCreator)) { // from DoorWindowInfo has higher priority if (oldCreator.CreatedFromDoorWindowInfo) { if (!oldCreator.HasValidGeometry && creator.HasValidGeometry) { oldCreator.CopyGeometry(creator); } } else if (creator.CreatedFromDoorWindowInfo) { if (!creator.HasValidGeometry && oldCreator.HasValidGeometry) { creator.CopyGeometry(oldCreator); } existingOpenings[levelIdToUse] = creator; } } else existingOpenings[levelIdToUse] = creator; }
/// <summary> /// Adds openings to an element. /// </summary> /// <param name="exporterIFC">The exporter.</param> /// <param name="elementHandles">The parent handles.</param> /// <param name="curveLoops">The parent CurveLoops.</param> /// <param name="element">The element.</param> /// <param name="plane">The plane.</param> /// <param name="scaledWidth">The width.</param> /// <param name="range">The range.</param> /// <param name="setter">The placement setter.</param> /// <param name="localPlacement">The local placement.</param> /// <param name="localWrapper">The wrapper.</param> public static void AddOpeningsToElement(ExporterIFC exporterIFC, IList <IFCAnyHandle> elementHandles, IList <CurveLoop> curveLoops, Element element, Plane plane, double scaledWidth, IFCRange range, PlacementSetter setter, IFCAnyHandle localPlacement, ProductWrapper localWrapper) { IList <IFCOpeningData> openingDataList = ExporterIFCUtils.GetOpeningData(exporterIFC, element, plane, range); IFCFile file = exporterIFC.GetFile(); IFCAnyHandle ownerHistory = exporterIFC.GetOwnerHistoryHandle(); foreach (IFCOpeningData openingData in openingDataList) { Element openingElem = element.Document.GetElement(openingData.OpeningElementId); if (openingElem == null) { openingElem = element; } // Don't export the opening if WallSweep category has been turned off. // This is currently restricted to WallSweeps because the element responsible for the opening could be a variety of things, including a line as part of the elevation profile of the wall. // As such, we will restrict which element types we check for CanExportElement. if ((openingElem is WallSweep) && (!ElementFilteringUtil.CanExportElement(exporterIFC, openingElem, true))) { continue; } IList <IFCExtrusionData> extrusionDataList = openingData.GetExtrusionData(); IFCAnyHandle parentHandle = null; if (elementHandles.Count > 1 && extrusionDataList.Count > 0) { parentHandle = FindParentHandle(elementHandles, curveLoops, extrusionDataList[0].GetLoops()[0]); } if (parentHandle == null) { parentHandle = elementHandles[0]; } bool isDoorOrWindowOpening = IsDoorOrWindowOpening(exporterIFC, openingElem, element); if (isDoorOrWindowOpening) { DoorWindowDelayedOpeningCreator delayedCreator = DoorWindowDelayedOpeningCreator.Create(exporterIFC, openingData, scaledWidth, element.Id, parentHandle, setter.LevelId); if (delayedCreator != null) { ExporterCacheManager.DoorWindowDelayedOpeningCreatorCache.Add(delayedCreator); continue; } } bool canUseElementGUID = !isDoorOrWindowOpening; IList <Solid> solids = openingData.GetOpeningSolids(); foreach (Solid solid in solids) { using (IFCExtrusionCreationData extrusionCreationData = new IFCExtrusionCreationData()) { extrusionCreationData.SetLocalPlacement(ExporterUtil.CreateLocalPlacement(file, localPlacement, null)); extrusionCreationData.ReuseLocalPlacement = true; string openingGUID = null; if (canUseElementGUID) { openingGUID = GUIDUtil.CreateGUID(openingElem); canUseElementGUID = false; } else { openingGUID = GUIDUtil.CreateGUID(); } CreateOpening(exporterIFC, parentHandle, element, openingElem, openingGUID, solid, scaledWidth, openingData.IsRecess, extrusionCreationData, setter, localWrapper); } } foreach (IFCExtrusionData extrusionData in extrusionDataList) { if (extrusionData.ScaledExtrusionLength < MathUtil.Eps()) { extrusionData.ScaledExtrusionLength = scaledWidth; } string openingGUID = null; if (canUseElementGUID) { openingGUID = GUIDUtil.CreateGUID(element); canUseElementGUID = false; } else { openingGUID = GUIDUtil.CreateGUID(); } CreateOpening(exporterIFC, parentHandle, localPlacement, element, openingElem, openingGUID, extrusionData, plane, openingData.IsRecess, setter, localWrapper); } } }
/// <summary> /// Adds openings to an element. /// </summary> /// <param name="exporterIFC">The exporter.</param> /// <param name="elementHandles">The parent handles.</param> /// <param name="curveLoops">The parent CurveLoops.</param> /// <param name="element">The element.</param> /// <param name="lcs">The local coordinate system.</param> /// <param name="scaledWidth">The width.</param> /// <param name="range">The range.</param> /// <param name="setter">The placement setter.</param> /// <param name="localPlacement">The local placement.</param> /// <param name="localWrapper">The wrapper.</param> public static void AddOpeningsToElement(ExporterIFC exporterIFC, IList<IFCAnyHandle> elementHandles, IList<CurveLoop> curveLoops, Element element, Transform lcs, double scaledWidth, IFCRange range, PlacementSetter setter, IFCAnyHandle localPlacement, ProductWrapper localWrapper) { IList<IFCOpeningData> openingDataList = ExporterIFCUtils.GetOpeningData(exporterIFC, element, lcs, range); IFCFile file = exporterIFC.GetFile(); IFCAnyHandle ownerHistory = ExporterCacheManager.OwnerHistoryHandle; foreach (IFCOpeningData openingData in openingDataList) { Element openingElem = element.Document.GetElement(openingData.OpeningElementId); if (openingElem == null) openingElem = element; bool currentWallIsHost = false; FamilyInstance openingFInst = openingElem as FamilyInstance; if (openingFInst != null && openingFInst.Host != null) { if (openingFInst.Host.Id == element.Id) currentWallIsHost = true; //continue; // If the host is not the current Wall, skip this opening } // Don't export the opening if WallSweep category has been turned off. // This is currently restricted to WallSweeps because the element responsible for the opening could be a variety of things, // including a line as part of the elevation profile of the wall. // As such, we will restrict which element types we check for CanExportElement. if ((openingElem is WallSweep) && (!ElementFilteringUtil.CanExportElement(exporterIFC, openingElem, true))) continue; IList<IFCExtrusionData> extrusionDataList = openingData.GetExtrusionData(); IFCAnyHandle parentHandle = null; if (elementHandles.Count > 1 && extrusionDataList.Count > 0) { parentHandle = FindParentHandle(elementHandles, curveLoops, extrusionDataList[0].GetLoops()[0]); } if (parentHandle == null) parentHandle = elementHandles[0]; bool isDoorOrWindowOpening = IsDoorOrWindowOpening(exporterIFC, openingElem, element); bool insertHasHost = false; bool insertInThisHost = false; if (openingElem is FamilyInstance && element is Wall) { string ifcEnumType; IFCExportInfoPair exportType = ExporterUtil.GetExportType(exporterIFC, openingElem, out ifcEnumType); Element instHost = (openingElem as FamilyInstance).Host; insertHasHost = (instHost != null); insertInThisHost = (insertHasHost && instHost.Id == element.Id); isDoorOrWindowOpening = insertInThisHost && (exportType.ExportInstance == IFCEntityType.IfcDoor || exportType.ExportType == IFCEntityType.IfcDoorType || exportType.ExportInstance == IFCEntityType.IfcWindow || exportType.ExportType == IFCEntityType.IfcWindowType); } if (isDoorOrWindowOpening && currentWallIsHost) { DoorWindowDelayedOpeningCreator delayedCreator = DoorWindowDelayedOpeningCreator.Create(exporterIFC, openingData, scaledWidth, element.Id, parentHandle, setter.LevelId); if (delayedCreator != null) { ExporterCacheManager.DoorWindowDelayedOpeningCreatorCache.Add(delayedCreator); continue; } } // If the opening is "filled" by another element (either a door or window as // determined above, or an embedded wall, then we can't use the element GUID // for the opening. bool canUseElementGUID = (!insertHasHost || insertInThisHost) && !isDoorOrWindowOpening && !(openingElem is Wall); IList<Solid> solids = openingData.GetOpeningSolids(); foreach (Solid solid in solids) { using (IFCExtrusionCreationData extrusionCreationData = new IFCExtrusionCreationData()) { extrusionCreationData.SetLocalPlacement(ExporterUtil.CreateLocalPlacement(file, localPlacement, null)); extrusionCreationData.ReuseLocalPlacement = true; string openingGUID = CreateOpeningGUID(openingElem, canUseElementGUID); canUseElementGUID = false; // Either it was used above, and therefore is now false, or it was already false. CreateOpening(exporterIFC, parentHandle, element, openingElem, openingGUID, solid, scaledWidth, openingData.IsRecess, extrusionCreationData, setter, localWrapper); } } foreach (IFCExtrusionData extrusionData in extrusionDataList) { if (extrusionData.ScaledExtrusionLength < MathUtil.Eps()) extrusionData.ScaledExtrusionLength = scaledWidth; string openingGUID = CreateOpeningGUID(openingElem, canUseElementGUID); canUseElementGUID = false; // Either it was used above, and therefore is now false, or it was already false. CreateOpening(exporterIFC, parentHandle, localPlacement, element, openingElem, openingGUID, extrusionData, lcs, openingData.IsRecess, setter, localWrapper); } } }
/// <summary> /// Creates a creator from IFCOpeningData. /// </summary> /// <param name="exporterIFC">The exporter.</param> /// <param name="openingData">The IFCOpeningData.</param> /// <param name="scaledHostWidth">The scaled host width.</param> /// <param name="hostId">The host id.</param> /// <param name="hostHnd">The host handle.</param> /// <param name="levelId">The base level id.</param> /// <returns>The creator.</returns> public static DoorWindowDelayedOpeningCreator Create(ExporterIFC exporterIFC, IFCOpeningData openingData, double scaledHostWidth, ElementId hostId, IFCAnyHandle hostHnd, ElementId levelId) { DoorWindowDelayedOpeningCreator creator = new DoorWindowDelayedOpeningCreator(); creator.InsertId = openingData.OpeningElementId; creator.HostId = hostId; creator.HostHnd = hostHnd; creator.ExtrusionData = openingData.GetExtrusionData(); creator.Solids = openingData.GetOpeningSolids(); creator.IsRecess = openingData.IsRecess; creator.CreatedFromDoorWindowInfo = false; creator.ScaledHostWidth = scaledHostWidth; creator.LevelId = levelId; if ((creator.ExtrusionData != null && creator.ExtrusionData.Count > 0) || (creator.Solids != null && creator.Solids.Count >0)) creator.HasValidGeometry = true; return creator; }
/// <summary> /// Creates a creator from DoorWindowInfo. /// </summary> /// <param name="exporterIFC">The exporter.</param> /// <param name="doorWindowInfo">The DoorWindowInfo.</param> /// <param name="instanceHandle">The instance handle.</param> /// <param name="levelId">The level id.</param> /// <returns>The creator.</returns> public static DoorWindowDelayedOpeningCreator Create(ExporterIFC exporterIFC, DoorWindowInfo doorWindowInfo, IFCAnyHandle instanceHandle, ElementId levelId) { if (exporterIFC == null || doorWindowInfo == null) return null; DoorWindowDelayedOpeningCreator doorWindowDelayedOpeningCreator = null; if (doorWindowInfo.HasRealWallHost) { Document doc = doorWindowInfo.HostObject.Document; Wall wall = doorWindowInfo.HostObject as Wall; FamilyInstance famInst = doorWindowInfo.InsertInstance; ElementId hostId = wall != null ? wall.Id : ElementId.InvalidElementId; ElementId instId = famInst != null ? famInst.Id : ElementId.InvalidElementId; doorWindowDelayedOpeningCreator = new DoorWindowDelayedOpeningCreator(); doorWindowDelayedOpeningCreator.HostId = hostId; doorWindowDelayedOpeningCreator.InsertId = instId; doorWindowDelayedOpeningCreator.PosHingeSide = doorWindowInfo.PosHingeSide; doorWindowDelayedOpeningCreator.DoorWindowHnd = instanceHandle; doorWindowDelayedOpeningCreator.LevelId = levelId; doorWindowDelayedOpeningCreator.CreatedFromDoorWindowInfo = true; WallType wallType = doc.GetElement(wall.GetTypeId()) as WallType; double unScaledWidth = ((wallType != null) && (wallType.Kind != WallKind.Curtain)) ? wallType.Width : 0.0; if (!MathUtil.IsAlmostZero(unScaledWidth)) { IFCAnyHandle openingHnd = exporterIFC.GetDoorWindowOpeningHandle(instId); if (IFCAnyHandleUtil.IsNullOrHasNoValue(openingHnd)) { XYZ cutDir = null; CurveLoop cutLoop = null; try { cutLoop = ExporterIFCUtils.GetInstanceCutoutFromWall(wall.Document, wall, famInst, out cutDir); } catch { cutLoop = null; // Couldn't create opening for door in wall - report as error in log when we create log file. } if (cutLoop != null) { if (doorWindowDelayedOpeningCreator.ExtrusionData == null) doorWindowDelayedOpeningCreator.ExtrusionData = new List<IFCExtrusionData>(); IFCExtrusionData extrusionData = new IFCExtrusionData(); extrusionData.ExtrusionDirection = cutDir; extrusionData.ScaledExtrusionLength = UnitUtil.ScaleLength(unScaledWidth); extrusionData.AddLoop(cutLoop); doorWindowDelayedOpeningCreator.ScaledHostWidth = UnitUtil.ScaleLength(unScaledWidth); doorWindowDelayedOpeningCreator.ExtrusionData.Add(extrusionData); doorWindowDelayedOpeningCreator.HasValidGeometry = true; } else { // Couldn't create opening for door in wall - report as error in log when we create log file. } } } } return doorWindowDelayedOpeningCreator; }
/// <summary> /// Copies geometries from another creator. /// </summary> /// <param name="otherCreator">The other creator.</param> public void CopyGeometry(DoorWindowDelayedOpeningCreator otherCreator) { ExtrusionData = otherCreator.ExtrusionData; Solids = otherCreator.Solids; IsRecess = otherCreator.IsRecess; ScaledHostWidth = otherCreator.ScaledHostWidth; if ((ExtrusionData != null && ExtrusionData.Count > 0) || (Solids != null && Solids.Count > 0)) HasValidGeometry = true; }
/// <summary> /// Creates a creator from DoorWindowInfo. /// </summary> /// <param name="exporterIFC">The exporter.</param> /// <param name="doorWindowInfo">The DoorWindowInfo.</param> /// <param name="instanceHandle">The instance handle.</param> /// <param name="levelId">The level id.</param> /// <returns>The creator.</returns> public static DoorWindowDelayedOpeningCreator Create(ExporterIFC exporterIFC, DoorWindowInfo doorWindowInfo, IFCAnyHandle instanceHandle, ElementId levelId) { if (exporterIFC == null || doorWindowInfo == null) { return(null); } DoorWindowDelayedOpeningCreator doorWindowDelayedOpeningCreator = null; if (doorWindowInfo.HasRealWallHost) { Document doc = doorWindowInfo.HostObject.Document; Wall wall = doorWindowInfo.HostObject as Wall; FamilyInstance famInst = doorWindowInfo.InsertInstance; ElementId hostId = wall != null ? wall.Id : ElementId.InvalidElementId; ElementId instId = famInst != null ? famInst.Id : ElementId.InvalidElementId; doorWindowDelayedOpeningCreator = new DoorWindowDelayedOpeningCreator(); doorWindowDelayedOpeningCreator.HostId = hostId; doorWindowDelayedOpeningCreator.InsertId = instId; doorWindowDelayedOpeningCreator.PosHingeSide = doorWindowInfo.PosHingeSide; doorWindowDelayedOpeningCreator.DoorWindowHnd = instanceHandle; doorWindowDelayedOpeningCreator.LevelId = levelId; doorWindowDelayedOpeningCreator.CreatedFromDoorWindowInfo = true; WallType wallType = doc.GetElement(wall.GetTypeId()) as WallType; double unScaledWidth = ((wallType != null) && (wallType.Kind != WallKind.Curtain)) ? wallType.Width : 0.0; if (!MathUtil.IsAlmostZero(unScaledWidth)) { IFCAnyHandle openingHnd = exporterIFC.GetDoorWindowOpeningHandle(instId); if (IFCAnyHandleUtil.IsNullOrHasNoValue(openingHnd)) { XYZ cutDir = null; CurveLoop cutLoop = null; try { cutLoop = ExporterIFCUtils.GetInstanceCutoutFromWall(wall.Document, wall, famInst, out cutDir); } catch { cutLoop = null; // Couldn't create opening for door in wall - report as error in log when we create log file. } if (cutLoop != null) { if (doorWindowDelayedOpeningCreator.ExtrusionData == null) { doorWindowDelayedOpeningCreator.ExtrusionData = new List <IFCExtrusionData>(); } IFCExtrusionData extrusionData = new IFCExtrusionData(); extrusionData.ExtrusionDirection = cutDir; extrusionData.ScaledExtrusionLength = UnitUtil.ScaleLength(unScaledWidth); extrusionData.AddLoop(cutLoop); doorWindowDelayedOpeningCreator.ScaledHostWidth = UnitUtil.ScaleLength(unScaledWidth); doorWindowDelayedOpeningCreator.ExtrusionData.Add(extrusionData); doorWindowDelayedOpeningCreator.HasValidGeometry = true; } else { // Couldn't create opening for door in wall - report as error in log when we create log file. } } } } return(doorWindowDelayedOpeningCreator); }
/// <summary> /// Adds openings to an element. /// </summary> /// <param name="exporterIFC">The exporter.</param> /// <param name="elementHandles">The parent handles.</param> /// <param name="curveLoops">The parent CurveLoops.</param> /// <param name="element">The element.</param> /// <param name="lcs">The local coordinate system.</param> /// <param name="scaledWidth">The width.</param> /// <param name="range">The range.</param> /// <param name="setter">The placement setter.</param> /// <param name="localPlacement">The local placement.</param> /// <param name="localWrapper">The wrapper.</param> public static void AddOpeningsToElement(ExporterIFC exporterIFC, IList <IFCAnyHandle> elementHandles, IList <CurveLoop> curveLoops, Element element, Transform lcs, double scaledWidth, IFCRange range, PlacementSetter setter, IFCAnyHandle localPlacement, ProductWrapper localWrapper) { if (lcs == null && ((curveLoops?.Count ?? 0) > 0)) { // assumption: first curve loop defines the plane. Plane hostObjPlane = curveLoops[0].HasPlane() ? curveLoops[0].GetPlane(): null; if (hostObjPlane != null) { lcs = GeometryUtil.CreateTransformFromPlane(hostObjPlane); } } IList <IFCOpeningData> openingDataList = ExporterIFCUtils.GetOpeningData(exporterIFC, element, lcs, range); IFCFile file = exporterIFC.GetFile(); int openingIndex = 0; foreach (IFCOpeningData openingData in openingDataList) { openingIndex++; Element openingElem = element.Document.GetElement(openingData.OpeningElementId); if (openingElem == null) { openingElem = element; } bool currentWallIsHost = false; FamilyInstance openingFInst = openingElem as FamilyInstance; if (openingFInst != null && openingFInst.Host != null) { if (openingFInst.Host.Id == element.Id) { currentWallIsHost = true; } } // Don't export the opening if WallSweep category has been turned off. // This is currently restricted to WallSweeps because the element responsible for the opening could be a variety of things, // including a line as part of the elevation profile of the wall. // As such, we will restrict which element types we check for CanExportElement. if ((openingElem is WallSweep) && (!ElementFilteringUtil.CanExportElement(exporterIFC, openingElem, true))) { continue; } IList <IFCExtrusionData> extrusionDataList = openingData.GetExtrusionData(); IFCAnyHandle parentHandle = FindParentHandle(elementHandles, curveLoops, extrusionDataList); string predefinedType; IFCExportInfoPair exportType = ExporterUtil.GetProductExportType(exporterIFC, openingElem, out predefinedType); bool exportingDoorOrWindow = (exportType.ExportInstance == IFCEntityType.IfcDoor || exportType.ExportType == IFCEntityType.IfcDoorType || exportType.ExportInstance == IFCEntityType.IfcWindow || exportType.ExportType == IFCEntityType.IfcWindowType); bool isDoorOrWindowOpening = IsDoorOrWindowOpening(openingElem, element, exportingDoorOrWindow); if (isDoorOrWindowOpening && currentWallIsHost) { DoorWindowDelayedOpeningCreator delayedCreator = DoorWindowDelayedOpeningCreator.Create(exporterIFC, openingData, scaledWidth, element.Id, parentHandle, setter.LevelId); if (delayedCreator != null) { ExporterCacheManager.DoorWindowDelayedOpeningCreatorCache.Add(delayedCreator); continue; } } IList <Solid> solids = openingData.GetOpeningSolids(); int solidIndex = 0; foreach (Solid solid in solids) { solidIndex++; using (IFCExtrusionCreationData extrusionCreationData = new IFCExtrusionCreationData()) { extrusionCreationData.SetLocalPlacement(ExporterUtil.CreateLocalPlacement(file, localPlacement, null)); extrusionCreationData.ReuseLocalPlacement = true; string openingGUID = CreateOpeningGUID(openingElem, range, openingIndex, solidIndex); CreateOpening(exporterIFC, parentHandle, element, openingElem, openingGUID, solid, scaledWidth, openingData.IsRecess, extrusionCreationData, setter, localWrapper); } } foreach (IFCExtrusionData extrusionData in extrusionDataList) { solidIndex++; if (extrusionData.ScaledExtrusionLength < MathUtil.Eps()) { extrusionData.ScaledExtrusionLength = scaledWidth; } string openingGUID = CreateOpeningGUID(openingElem, range, openingIndex, solidIndex); CreateOpening(exporterIFC, parentHandle, localPlacement, element, openingElem, openingGUID, extrusionData, lcs, openingData.IsRecess, setter, localWrapper); } } }