/// <summary> /// Creates openings if there is necessary. /// </summary> /// <param name="elementHandle">The element handle to create openings.</param> /// <param name="element">The element to create openings.</param> /// <param name="info">The extrusion data.</param> /// <param name="extraParams">The extrusion creation data.</param> /// <param name="offsetTransform">The offset transform from ExportBody, or the identity transform.</param> /// <param name="exporterIFC">The ExporterIFC object.</param> /// <param name="originalPlacement">The original placement handle.</param> /// <param name="setter">The PlacementSetter.</param> /// <param name="wrapper">The ProductWrapper.</param> private static void CreateOpeningsIfNecessaryBase(IFCAnyHandle elementHandle, Element element, IList<IFCExtrusionData> info, IFCExtrusionCreationData extraParams, Transform offsetTransform, ExporterIFC exporterIFC, IFCAnyHandle originalPlacement, PlacementSetter setter, ProductWrapper wrapper) { if (IFCAnyHandleUtil.IsNullOrHasNoValue(elementHandle)) return; int sz = info.Count; if (sz == 0) return; using (TransformSetter transformSetter = TransformSetter.Create()) { if (offsetTransform != null) transformSetter.Initialize(exporterIFC, offsetTransform.Inverse); IFCFile file = exporterIFC.GetFile(); ElementId categoryId = CategoryUtil.GetSafeCategoryId(element); Document document = element.Document; string openingObjectType = "Opening"; int openingNumber = 1; for (int curr = info.Count - 1; curr >= 0; curr--) { IFCAnyHandle extrusionHandle = ExtrusionExporter.CreateExtrudedSolidFromExtrusionData(exporterIFC, element, info[curr]); if (IFCAnyHandleUtil.IsNullOrHasNoValue(extrusionHandle)) continue; IFCAnyHandle styledItemHnd = BodyExporter.CreateSurfaceStyleForRepItem(exporterIFC, document, extrusionHandle, ElementId.InvalidElementId); HashSet<IFCAnyHandle> bodyItems = new HashSet<IFCAnyHandle>(); bodyItems.Add(extrusionHandle); IFCAnyHandle contextOfItems = exporterIFC.Get3DContextHandle("Body"); IFCAnyHandle bodyRep = RepresentationUtil.CreateSweptSolidRep(exporterIFC, element, categoryId, contextOfItems, bodyItems, null); IList<IFCAnyHandle> representations = new List<IFCAnyHandle>(); representations.Add(bodyRep); IFCAnyHandle openingRep = IFCInstanceExporter.CreateProductDefinitionShape(file, null, null, representations); IFCAnyHandle openingPlacement = ExporterUtil.CopyLocalPlacement(file, originalPlacement); string guid = GUIDUtil.CreateGUID(); IFCAnyHandle ownerHistory = exporterIFC.GetOwnerHistoryHandle(); string openingName = NamingUtil.GetIFCNamePlusIndex(element, openingNumber++); string elementId = NamingUtil.CreateIFCElementId(element); IFCAnyHandle openingElement = IFCInstanceExporter.CreateOpeningElement(file, guid, ownerHistory, openingName, null, openingObjectType, openingPlacement, openingRep, elementId); wrapper.AddElement(null, openingElement, setter, extraParams, true); if (ExporterCacheManager.ExportOptionsCache.ExportBaseQuantities && (extraParams != null)) PropertyUtil.CreateOpeningQuantities(exporterIFC, openingElement, extraParams); string voidGuid = GUIDUtil.CreateGUID(); IFCInstanceExporter.CreateRelVoidsElement(file, voidGuid, ownerHistory, null, null, elementHandle, openingElement); } } }
/// <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> /// 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> /// Creates openings associated with an extrusion, if there are any. /// </summary> /// <param name="elementHandle">The element handle to create openings.</param> /// <param name="element">The element to create openings.</param> /// <param name="extraParams">The extrusion creation data.</param> /// <param name="exporterIFC">The ExporterIFC object.</param> /// <param name="originalPlacement">The original placement handle.</param> /// <param name="setter">The PlacementSetter.</param> /// <param name="wrapper">The ProductWrapper.</param> public static void CreateOpeningsIfNecessary(IFCAnyHandle elementHandle, Element element, IFCExtrusionCreationData extraParams, Transform offsetTransform, ExporterIFC exporterIFC, IFCAnyHandle originalPlacement, PlacementSetter setter, ProductWrapper wrapper) { if (IFCAnyHandleUtil.IsNullOrHasNoValue(elementHandle)) return; ElementId categoryId = CategoryUtil.GetSafeCategoryId(element); IList<IFCExtrusionData> info = extraParams.GetOpenings(); CreateOpeningsIfNecessaryBase(elementHandle, element, info, extraParams, offsetTransform, exporterIFC, originalPlacement, setter, wrapper); extraParams.ClearOpenings(); }
/// <summary> /// Creates openings associated with an extrusion, if there are any. /// </summary> /// <param name="elementHandle">The element handle to create openings.</param> /// <param name="element">The element to create openings.</param> /// <param name="info">The extrusion data.</param> /// <param name="offsetTransform">The offset transform from ExportBody, or the identity transform.</param> /// <param name="exporterIFC">The ExporterIFC object.</param> /// <param name="originalPlacement">The original placement handle.</param> /// <param name="setter">The PlacementSetter.</param> /// <param name="wrapper">The ProductWrapper.</param> public static void CreateOpeningsIfNecessary(IFCAnyHandle elementHandle, Element element, IList<IFCExtrusionData> info, Transform offsetTransform, ExporterIFC exporterIFC, IFCAnyHandle originalPlacement, PlacementSetter setter, ProductWrapper wrapper) { if (IFCAnyHandleUtil.IsNullOrHasNoValue(elementHandle)) return; using (IFCExtrusionCreationData extraParams = new IFCExtrusionCreationData()) { CreateOpeningsIfNecessaryBase(elementHandle, element, info, extraParams, offsetTransform, exporterIFC, originalPlacement, setter, wrapper); } }
/// <summary> /// Exports curtain object as one Brep. /// </summary> /// <param name="allSubElements"> /// Collection of elements contained in the host curtain element. /// </param> /// <param name="wallElement"> /// The curtain wall element. /// </param> /// <param name="exporterIFC"> /// The ExporterIFC object. /// </param> /// <param name="setter"> /// The PlacementSetter object. /// </param> /// <param name="localPlacement"> /// The local placement handle. /// </param> /// <returns> /// The handle. /// </returns> public static IFCAnyHandle ExportCurtainObjectCommonAsOneBRep(ICollection<ElementId> allSubElements, Element wallElement, ExporterIFC exporterIFC, PlacementSetter setter, IFCAnyHandle localPlacement) { IFCAnyHandle prodDefRep = null; Document document = wallElement.Document; double eps = UnitUtil.ScaleLength(document.Application.VertexTolerance); IFCFile file = exporterIFC.GetFile(); IFCAnyHandle contextOfItems = exporterIFC.Get3DContextHandle("Body"); IFCGeometryInfo info = IFCGeometryInfo.CreateFaceGeometryInfo(eps); ISet<IFCAnyHandle> bodyItems = new HashSet<IFCAnyHandle>(); // Want to make sure we don't accidentally add a mullion or curtain line more than once. HashSet<ElementId> alreadyVisited = new HashSet<ElementId>(); Options geomOptions = GeometryUtil.GetIFCExportGeometryOptions(); foreach (ElementId subElemId in allSubElements) { Element subElem = wallElement.Document.GetElement(subElemId); GeometryElement geomElem = subElem.get_Geometry(geomOptions); if (geomElem == null) continue; if (alreadyVisited.Contains(subElem.Id)) continue; alreadyVisited.Add(subElem.Id); ExporterIFCUtils.CollectGeometryInfo(exporterIFC, info, geomElem, XYZ.Zero, false); HashSet<IFCAnyHandle> faces = new HashSet<IFCAnyHandle>(info.GetSurfaces()); IFCAnyHandle outer = IFCInstanceExporter.CreateClosedShell(file, faces); if (!IFCAnyHandleUtil.IsNullOrHasNoValue(outer)) bodyItems.Add(RepresentationUtil.CreateFacetedBRep(exporterIFC, document, outer, ElementId.InvalidElementId)); } if (bodyItems.Count == 0) return prodDefRep; ElementId catId = CategoryUtil.GetSafeCategoryId(wallElement); IFCAnyHandle shapeRep = RepresentationUtil.CreateBRepRep(exporterIFC, wallElement, catId, contextOfItems, bodyItems); if (IFCAnyHandleUtil.IsNullOrHasNoValue(shapeRep)) return prodDefRep; IList<IFCAnyHandle> shapeReps = new List<IFCAnyHandle>(); shapeReps.Add(shapeRep); IFCAnyHandle boundingBoxRep = BoundingBoxExporter.ExportBoundingBox(exporterIFC, wallElement.get_Geometry(geomOptions), Transform.Identity); if (boundingBoxRep != null) shapeReps.Add(boundingBoxRep); prodDefRep = IFCInstanceExporter.CreateProductDefinitionShape(file, null, null, shapeReps); return prodDefRep; }
/// <summary> /// Creates IFC room/space/area item, not include boundaries. /// </summary> /// <param name="exporterIFC">The ExporterIFC object.</param> /// <param name="spatialElement">The spatial element.</param> /// <param name="productWrapper">The ProductWrapper.</param> /// <param name="setter">The PlacementSetter.</param> /// <returns>True if created successfully, false otherwise.</returns> static bool CreateIFCSpace(ExporterIFC exporterIFC, SpatialElement spatialElement, ProductWrapper productWrapper, PlacementSetter setter, out SpatialElementGeometryResults results) { results = null; IList<CurveLoop> curveLoops = null; try { // Avoid throwing for a spatial element with no location. if (spatialElement.Location == null) return false; SpatialElementBoundaryOptions options = GetSpatialElementBoundaryOptions(spatialElement); curveLoops = ExporterIFCUtils.GetRoomBoundaryAsCurveLoopArray(spatialElement, options, true); } catch (Autodesk.Revit.Exceptions.InvalidOperationException) { //Some spatial elements are not placed that have no boundary loops. Don't export them. return false; } Autodesk.Revit.DB.Document document = spatialElement.Document; ElementId levelId = spatialElement.LevelId; ElementId catId = spatialElement.Category != null ? spatialElement.Category.Id : ElementId.InvalidElementId; double dArea = 0.0; if (ParameterUtil.GetDoubleValueFromElement(spatialElement, BuiltInParameter.ROOM_AREA, out dArea) != null) dArea = UnitUtil.ScaleArea(dArea); IFCLevelInfo levelInfo = exporterIFC.GetLevelInfo(levelId); string strSpaceNumber = null; string strSpaceName = null; string strSpaceDesc = null; if (ParameterUtil.GetStringValueFromElement(spatialElement, BuiltInParameter.ROOM_NUMBER, out strSpaceNumber) == null) strSpaceNumber = null; if (ParameterUtil.GetStringValueFromElement(spatialElement, BuiltInParameter.ROOM_NAME, out strSpaceName) == null) strSpaceName = null; if (ParameterUtil.GetStringValueFromElement(spatialElement, BuiltInParameter.ALL_MODEL_INSTANCE_COMMENTS, out strSpaceDesc) == null) strSpaceDesc = null; string name = strSpaceNumber; string longName = strSpaceName; string desc = strSpaceDesc; IFCFile file = exporterIFC.GetFile(); IFCAnyHandle localPlacement = setter.LocalPlacement; ElementType elemType = document.GetElement(spatialElement.GetTypeId()) as ElementType; IFCInternalOrExternal internalOrExternal = CategoryUtil.IsElementExternal(spatialElement) ? IFCInternalOrExternal.External : IFCInternalOrExternal.Internal; double scaledRoomHeight = GetScaledHeight(spatialElement, levelId, levelInfo); if (scaledRoomHeight <= 0.0) return false; double bottomOffset; ParameterUtil.GetDoubleValueFromElement(spatialElement, BuiltInParameter.ROOM_LOWER_OFFSET, out bottomOffset); double elevation = (levelInfo != null) ? levelInfo.Elevation : 0.0; XYZ zDir = new XYZ(0, 0, 1); XYZ orig = new XYZ(0, 0, elevation + bottomOffset); Plane plane = new Plane(zDir, orig); // room calculated as level offset. GeometryElement geomElem = null; bool isArea = (spatialElement is Area); Area spatialElementAsArea = isArea ? (spatialElement as Area) : null; if (spatialElement is Autodesk.Revit.DB.Architecture.Room) { Autodesk.Revit.DB.Architecture.Room room = spatialElement as Autodesk.Revit.DB.Architecture.Room; geomElem = room.ClosedShell; } else if (spatialElement is Autodesk.Revit.DB.Mechanical.Space) { Autodesk.Revit.DB.Mechanical.Space space = spatialElement as Autodesk.Revit.DB.Mechanical.Space; geomElem = space.ClosedShell; } else if (isArea) { Options geomOptions = GeometryUtil.GetIFCExportGeometryOptions(); geomElem = spatialElementAsArea.get_Geometry(geomOptions); } IFCAnyHandle spaceHnd = null; string spatialElementName = null; using (IFCExtrusionCreationData extraParams = new IFCExtrusionCreationData()) { extraParams.SetLocalPlacement(localPlacement); extraParams.PossibleExtrusionAxes = IFCExtrusionAxes.TryZ; using (IFCTransaction transaction2 = new IFCTransaction(file)) { IFCAnyHandle repHnd = null; if (!ExporterCacheManager.ExportOptionsCache.Use2DRoomBoundaryForRoomVolumeCreation && geomElem != null) { BodyExporterOptions bodyExporterOptions = new BodyExporterOptions(true); bodyExporterOptions.TessellationLevel = BodyExporter.GetTessellationLevel(); repHnd = RepresentationUtil.CreateAppropriateProductDefinitionShape(exporterIFC, spatialElement, catId, geomElem, bodyExporterOptions, null, extraParams, false); if (IFCAnyHandleUtil.IsNullOrHasNoValue(repHnd)) extraParams.ClearOpenings(); } else { IFCAnyHandle shapeRep = ExtrusionExporter.CreateExtrudedSolidFromCurveLoop(exporterIFC, null, curveLoops, plane, zDir, scaledRoomHeight); if (IFCAnyHandleUtil.IsNullOrHasNoValue(shapeRep)) return false; IFCAnyHandle styledItemHnd = BodyExporter.CreateSurfaceStyleForRepItem(exporterIFC, document, shapeRep, ElementId.InvalidElementId); HashSet<IFCAnyHandle> bodyItems = new HashSet<IFCAnyHandle>(); bodyItems.Add(shapeRep); shapeRep = RepresentationUtil.CreateSweptSolidRep(exporterIFC, spatialElement, catId, exporterIFC.Get3DContextHandle("Body"), bodyItems, null); IList<IFCAnyHandle> shapeReps = new List<IFCAnyHandle>(); shapeReps.Add(shapeRep); IFCAnyHandle boundingBoxRep = BoundingBoxExporter.ExportBoundingBox(exporterIFC, geomElem, Transform.Identity); if (boundingBoxRep != null) shapeReps.Add(boundingBoxRep); repHnd = IFCInstanceExporter.CreateProductDefinitionShape(file, null, null, shapeReps); } extraParams.ScaledHeight = scaledRoomHeight; extraParams.ScaledArea = dArea; spatialElementName = NamingUtil.GetNameOverride(spatialElement, name); string spatialElementDescription = NamingUtil.GetDescriptionOverride(spatialElement, desc); string spatialElementObjectType = NamingUtil.GetObjectTypeOverride(spatialElement, null); string spatialElementLongName = NamingUtil.GetLongNameOverride(spatialElement, longName); double? spaceElevationWithFlooring = null; double elevationWithFlooring = 0.0; if (ParameterUtil.GetDoubleValueFromElement(spatialElement, null, "IfcElevationWithFlooring", out elevationWithFlooring) != null) spaceElevationWithFlooring = UnitUtil.ScaleLength(elevationWithFlooring); spaceHnd = IFCInstanceExporter.CreateSpace(file, GUIDUtil.CreateGUID(spatialElement), ExporterCacheManager.OwnerHistoryHandle, spatialElementName, spatialElementDescription, spatialElementObjectType, extraParams.GetLocalPlacement(), repHnd, spatialElementLongName, Toolkit.IFCElementComposition.Element, internalOrExternal, spaceElevationWithFlooring); transaction2.Commit(); } if (spaceHnd != null) { productWrapper.AddSpace(spatialElement, spaceHnd, levelInfo, extraParams, true); if (isArea) { Element areaScheme = spatialElementAsArea.AreaScheme; if (areaScheme != null) { ElementId areaSchemeId = areaScheme.Id; HashSet<IFCAnyHandle> areas = null; if (!ExporterCacheManager.AreaSchemeCache.TryGetValue(areaSchemeId, out areas)) { areas = new HashSet<IFCAnyHandle>(); ExporterCacheManager.AreaSchemeCache[areaSchemeId] = areas; } areas.Add(spaceHnd); } } } } // Save room handle for later use/relationships ExporterCacheManager.SpaceInfoCache.SetSpaceHandle(spatialElement, spaceHnd); // Find Ceiling as a Space boundary and keep the relationship in a cache for use later bool ret = GetCeilingSpaceBoundary(spatialElement, out results); if (!MathUtil.IsAlmostZero(dArea) && !(ExporterCacheManager.ExportOptionsCache.ExportAsCOBIE) && !ExporterCacheManager.ExportOptionsCache.ExportAs2x3CoordinationView2 && !ExporterCacheManager.ExportOptionsCache.ExportBaseQuantities) { bool isDesignGrossArea = (string.Compare(spatialElementName, "GSA Design Gross Area") > 0); PropertyUtil.CreatePreCOBIEGSAQuantities(exporterIFC, spaceHnd, "GSA Space Areas", (isDesignGrossArea ? "GSA Design Gross Area" : "GSA BIM Area"), dArea); } // Export Classifications for SpatialElement for GSA/COBIE. if (ExporterCacheManager.ExportOptionsCache.ExportAsCOBIE) { ProjectInfo projectInfo = document.ProjectInformation; if (projectInfo != null) CreateCOBIESpaceClassifications(exporterIFC, file, spaceHnd, projectInfo, spatialElement); } return true; }
/// <summary> /// Exports mullion. /// </summary> /// <param name="exporterIFC"> /// The ExporterIFC object. /// </param> /// <param name="mullion"> /// The mullion object. /// </param> /// <param name="geometryElement"> /// The geometry element. /// </param> /// <param name="localPlacement"> /// The local placement handle. /// </param> /// <param name="setter"> /// The PlacementSetter. /// </param> /// <param name="productWrapper"> /// The ProductWrapper. /// </param> public static void Export(ExporterIFC exporterIFC, Mullion mullion, GeometryElement geometryElement, IFCAnyHandle localPlacement, PlacementSetter setter, ProductWrapper productWrapper) { IFCFile file = exporterIFC.GetFile(); using (PlacementSetter mullionSetter = PlacementSetter.Create(exporterIFC, mullion)) { using (IFCExtrusionCreationData extraParams = new IFCExtrusionCreationData()) { IFCAnyHandle mullionPlacement = mullionSetter.LocalPlacement; Transform relTrf = ExporterIFCUtils.GetRelativeLocalPlacementOffsetTransform(localPlacement, mullionPlacement); Transform inverseTrf = relTrf.Inverse; IFCAnyHandle mullionLocalPlacement = ExporterUtil.CreateLocalPlacement(file, localPlacement, inverseTrf.Origin, inverseTrf.BasisZ, inverseTrf.BasisX); extraParams.SetLocalPlacement(mullionLocalPlacement); Transform extrusionLCS = null; // Add a custom direction for trying to create an extrusion based on the base curve of the mullion, if it is a line and not an arc. Curve baseCurve = mullion.LocationCurve; if ((baseCurve != null) && (baseCurve is Line)) { // We won't use curveBounds and origin yet; just need the axis for now. IFCRange curveBounds; XYZ origin, mullionDirection; GeometryUtil.GetAxisAndRangeFromCurve(baseCurve, out curveBounds, out mullionDirection, out origin); // approx 1.0/sqrt(2.0) XYZ planeY = (Math.Abs(mullionDirection.Z) < 0.707) ? XYZ.BasisZ.CrossProduct(mullionDirection) : XYZ.BasisX.CrossProduct(mullionDirection); planeY.Normalize(); XYZ projDir = mullionDirection.CrossProduct(planeY); extrusionLCS = Transform.Identity; extrusionLCS.BasisX = mullionDirection; extrusionLCS.BasisY = planeY; extrusionLCS.BasisZ = projDir; extrusionLCS.Origin = origin; } ElementId catId = CategoryUtil.GetSafeCategoryId(mullion); BodyExporterOptions bodyExporterOptions = new BodyExporterOptions(true); bodyExporterOptions.ExtrusionLocalCoordinateSystem = extrusionLCS; IFCAnyHandle repHnd = RepresentationUtil.CreateAppropriateProductDefinitionShape(exporterIFC, mullion, catId, geometryElement, bodyExporterOptions, null, extraParams, true); if (IFCAnyHandleUtil.IsNullOrHasNoValue(repHnd)) { extraParams.ClearOpenings(); return; } string elemGUID = GUIDUtil.CreateGUID(mullion); IFCAnyHandle ownerHistory = exporterIFC.GetOwnerHistoryHandle(); string elemObjectType = NamingUtil.CreateIFCObjectName(exporterIFC, mullion); string name = NamingUtil.GetNameOverride(mullion, elemObjectType); string description = NamingUtil.GetDescriptionOverride(mullion, null); string objectType = NamingUtil.GetObjectTypeOverride(mullion, elemObjectType); string elemTag = NamingUtil.GetTagOverride(mullion, NamingUtil.CreateIFCElementId(mullion)); IFCAnyHandle mullionHnd = IFCInstanceExporter.CreateMember(file, elemGUID, ownerHistory, name, description, objectType, mullionLocalPlacement, repHnd, elemTag, "MULLION"); ExporterCacheManager.HandleToElementCache.Register(mullionHnd, mullion.Id); productWrapper.AddElement(mullion, mullionHnd, mullionSetter, extraParams, false); ElementId matId = BodyExporter.GetBestMaterialIdFromGeometryOrParameter(geometryElement, exporterIFC, mullion); CategoryUtil.CreateMaterialAssociation(exporterIFC, mullionHnd, matId); } } }
/// <summary> /// Creates an opening from extrusion data. /// </summary> /// <param name="exporterIFC">The exporter.</param> /// <param name="hostObjHnd">The host handle.</param> /// <param name="hostPlacement">The host placement.</param> /// <param name="hostElement">The host element.</param> /// <param name="insertElement">The opening element.</param> /// <param name="openingGUID">The opening GUID.</param> /// <param name="extrusionData">The extrusion data.</param> /// <param name="plane">The plane.</param> /// <param name="isRecess">True if it is a recess.</param> /// <returns>The opening handle.</returns> static public IFCAnyHandle CreateOpening(ExporterIFC exporterIFC, IFCAnyHandle hostObjHnd, IFCAnyHandle hostPlacement, Element hostElement, Element insertElement, string openingGUID, IFCExtrusionData extrusionData, Plane plane, bool isRecess, PlacementSetter setter, ProductWrapper localWrapper) { IFCFile file = exporterIFC.GetFile(); IList<CurveLoop> curveLoops = extrusionData.GetLoops(); if (curveLoops.Count == 0) return null; if (plane == null) { // assumption: first curve loop defines the plane. if (!curveLoops[0].HasPlane()) return null; plane = curveLoops[0].GetPlane(); } ElementId catId = CategoryUtil.GetSafeCategoryId(insertElement); IFCAnyHandle openingProdRepHnd = RepresentationUtil.CreateExtrudedProductDefShape(exporterIFC, insertElement, catId, curveLoops, plane, extrusionData.ExtrusionDirection, extrusionData.ScaledExtrusionLength); string openingObjectType = isRecess ? "Recess" : "Opening"; IFCAnyHandle ownerHistory = exporterIFC.GetOwnerHistoryHandle(); string openingName = NamingUtil.GetNameOverride(insertElement, null); if (string.IsNullOrEmpty(openingName)) openingName = NamingUtil.GetNameOverride(hostElement, NamingUtil.CreateIFCObjectName(exporterIFC, hostElement)); IFCAnyHandle openingHnd = IFCInstanceExporter.CreateOpeningElement(file, openingGUID, ownerHistory, openingName, null, openingObjectType, ExporterUtil.CreateLocalPlacement(file, hostPlacement, null), openingProdRepHnd, null); IFCExtrusionCreationData ecData = null; if (ExporterCacheManager.ExportOptionsCache.ExportBaseQuantities) { double height, width; ecData = new IFCExtrusionCreationData(); if (GeometryUtil.ComputeHeightWidthOfCurveLoop(curveLoops[0], plane, out height, out width)) { ecData.ScaledHeight = UnitUtil.ScaleLength(height); ecData.ScaledWidth = UnitUtil.ScaleLength(width); } else { double area = ExporterIFCUtils.ComputeAreaOfCurveLoops(curveLoops); ecData.ScaledArea = UnitUtil.ScaleArea(area); } PropertyUtil.CreateOpeningQuantities(exporterIFC, openingHnd, ecData); } if (localWrapper != null) { Element elementForProperties = null; if (GUIDUtil.IsGUIDFor(insertElement, openingGUID)) elementForProperties = insertElement; localWrapper.AddElement(elementForProperties, openingHnd, setter, ecData, true); } string voidGuid = GUIDUtil.CreateGUID(); IFCInstanceExporter.CreateRelVoidsElement(file, voidGuid, ownerHistory, null, null, hostObjHnd, openingHnd); return openingHnd; }
/// <summary> /// Exports curtain object as container. /// </summary> /// <param name="allSubElements"> /// Collection of elements contained in the host curtain element. /// </param> /// <param name="wallElement"> /// The curtain wall element. /// </param> /// <param name="exporterIFC"> /// The ExporterIFC object. /// </param> /// <param name="productWrapper"> /// The ProductWrapper. /// </param> public static void ExportCurtainObjectCommonAsContainer(ICollection<ElementId> allSubElements, Element wallElement, ExporterIFC exporterIFC, ProductWrapper origWrapper, PlacementSetter currSetter) { if (wallElement == null) return; string overrideCADLayer = null; ParameterUtil.GetStringValueFromElementOrSymbol(wallElement, "IFCCadLayer", out overrideCADLayer); using (ExporterStateManager.CADLayerOverrideSetter layerSetter = new ExporterStateManager.CADLayerOverrideSetter(overrideCADLayer)) { HashSet<ElementId> alreadyVisited = new HashSet<ElementId>(); // just in case. Options geomOptions = GeometryUtil.GetIFCExportGeometryOptions(); { foreach (ElementId subElemId in allSubElements) { using (ProductWrapper productWrapper = ProductWrapper.Create(origWrapper)) { Element subElem = wallElement.Document.GetElement(subElemId); if (subElem == null) continue; if (alreadyVisited.Contains(subElem.Id)) continue; alreadyVisited.Add(subElem.Id); // Respect element visibility settings. if (!ElementFilteringUtil.CanExportElement(exporterIFC, subElem, false) || !ElementFilteringUtil.IsElementVisible(subElem)) continue; GeometryElement geomElem = subElem.get_Geometry(geomOptions); if (geomElem == null) continue; try { if (subElem is FamilyInstance) { if (subElem is Mullion) { if (ExporterCacheManager.ExportOptionsCache.ExportAs2x2) ProxyElementExporter.Export(exporterIFC, subElem, geomElem, productWrapper); else { IFCAnyHandle currLocalPlacement = currSetter.LocalPlacement; MullionExporter.Export(exporterIFC, subElem as Mullion, geomElem, currLocalPlacement, currSetter, productWrapper); } } else { FamilyInstance subFamInst = subElem as FamilyInstance; string ifcEnumType; IFCExportType exportType = ExporterUtil.GetExportType(exporterIFC, subElem, out ifcEnumType); if (exportType == IFCExportType.IfcCurtainWall) { // By default, panels and mullions are set to the same category as their parent. In this case, // ask to get the exportType from the category id, since we don't want to inherit the parent class. ElementId catId = CategoryUtil.GetSafeCategoryId(subElem); exportType = ElementFilteringUtil.GetExportTypeFromCategoryId(catId, out ifcEnumType); } if (ExporterCacheManager.ExportOptionsCache.ExportAs2x2) { if ((exportType == IFCExportType.DontExport) || (exportType == IFCExportType.IfcPlateType) || (exportType == IFCExportType.IfcMemberType)) exportType = IFCExportType.IfcBuildingElementProxyType; } else { if (exportType == IFCExportType.DontExport) { ifcEnumType = "CURTAIN_PANEL"; exportType = IFCExportType.IfcPlateType; } } IFCAnyHandle currLocalPlacement = currSetter.LocalPlacement; using (IFCExtrusionCreationData extraParams = new IFCExtrusionCreationData()) { FamilyInstanceExporter.ExportFamilyInstanceAsMappedItem(exporterIFC, subFamInst, exportType, ifcEnumType, productWrapper, ElementId.InvalidElementId, null, currLocalPlacement); } } } else if (subElem is CurtainGridLine) { ProxyElementExporter.Export(exporterIFC, subElem, geomElem, productWrapper); } else if (subElem is Wall) { WallExporter.ExportWall(exporterIFC, subElem, null, geomElem, productWrapper); } } catch (Exception ex) { if (ExporterUtil.IsFatalException(wallElement.Document, ex)) throw ex; continue; } } } } } }
/// <summary> /// Exports curtain object as one Brep. /// </summary> /// <param name="allSubElements"> /// Collection of elements contained in the host curtain element. /// </param> /// <param name="wallElement"> /// The curtain wall element. /// </param> /// <param name="exporterIFC"> /// The ExporterIFC object. /// </param> /// <param name="setter"> /// The PlacementSetter object. /// </param> /// <param name="localPlacement"> /// The local placement handle. /// </param> /// <returns> /// The handle. /// </returns> public static IFCAnyHandle ExportCurtainObjectCommonAsOneBRep(ICollection<ElementId> allSubElements, Element wallElement, ExporterIFC exporterIFC, PlacementSetter setter, IFCAnyHandle localPlacement) { IFCAnyHandle prodDefRep = null; Document document = wallElement.Document; double eps = UnitUtil.ScaleLength(document.Application.VertexTolerance); IFCFile file = exporterIFC.GetFile(); IFCAnyHandle contextOfItems = exporterIFC.Get3DContextHandle("Body"); IFCGeometryInfo info = IFCGeometryInfo.CreateFaceGeometryInfo(eps); ISet<IFCAnyHandle> bodyItems = new HashSet<IFCAnyHandle>(); // Want to make sure we don't accidentally add a mullion or curtain line more than once. HashSet<ElementId> alreadyVisited = new HashSet<ElementId>(); bool useFallbackBREP = true; Options geomOptions = GeometryUtil.GetIFCExportGeometryOptions(); foreach (ElementId subElemId in allSubElements) { Element subElem = wallElement.Document.GetElement(subElemId); GeometryElement geomElem = subElem.get_Geometry(geomOptions); if (geomElem == null) continue; if (alreadyVisited.Contains(subElem.Id)) continue; alreadyVisited.Add(subElem.Id); // Export tessellated geometry when IFC4 Reference View is selected if (ExporterCacheManager.ExportOptionsCache.ExportAs4ReferenceView) { BodyExporterOptions bodyExporterOptions = new BodyExporterOptions(false); IFCAnyHandle triFaceSet = BodyExporter.ExportBodyAsTriangulatedFaceSet(exporterIFC, subElem, bodyExporterOptions, geomElem); if (!IFCAnyHandleUtil.IsNullOrHasNoValue(triFaceSet)) { bodyItems.Add(triFaceSet); useFallbackBREP = false; // no need to do Brep since it is successful } } // Export AdvancedFace before use fallback BREP else if (ExporterCacheManager.ExportOptionsCache.ExportAs4DesignTransferView) { BodyExporterOptions bodyExporterOptions = new BodyExporterOptions(false); IFCAnyHandle advancedBRep = BodyExporter.ExportBodyAsAdvancedBrep(exporterIFC, subElem, bodyExporterOptions, geomElem); if (!IFCAnyHandleUtil.IsNullOrHasNoValue(advancedBRep)) { bodyItems.Add(advancedBRep); useFallbackBREP = false; // no need to do Brep since it is successful } } if (useFallbackBREP) { ExporterIFCUtils.CollectGeometryInfo(exporterIFC, info, geomElem, XYZ.Zero, false); HashSet<IFCAnyHandle> faces = new HashSet<IFCAnyHandle>(info.GetSurfaces()); IFCAnyHandle outer = IFCInstanceExporter.CreateClosedShell(file, faces); if (!IFCAnyHandleUtil.IsNullOrHasNoValue(outer)) bodyItems.Add(RepresentationUtil.CreateFacetedBRep(exporterIFC, document, outer, ElementId.InvalidElementId)); } } if (bodyItems.Count == 0) return prodDefRep; ElementId catId = CategoryUtil.GetSafeCategoryId(wallElement); IFCAnyHandle shapeRep; // Use tessellated geometry in Reference View if (ExporterCacheManager.ExportOptionsCache.ExportAs4ReferenceView && !useFallbackBREP) shapeRep = RepresentationUtil.CreateTessellatedRep(exporterIFC, wallElement, catId, contextOfItems, bodyItems, null); else if (ExporterCacheManager.ExportOptionsCache.ExportAs4DesignTransferView && !useFallbackBREP) shapeRep = RepresentationUtil.CreateAdvancedBRepRep(exporterIFC, wallElement, catId, contextOfItems, bodyItems, null); else shapeRep = RepresentationUtil.CreateBRepRep(exporterIFC, wallElement, catId, contextOfItems, bodyItems); if (IFCAnyHandleUtil.IsNullOrHasNoValue(shapeRep)) return prodDefRep; IList<IFCAnyHandle> shapeReps = new List<IFCAnyHandle>(); shapeReps.Add(shapeRep); IFCAnyHandle boundingBoxRep = BoundingBoxExporter.ExportBoundingBox(exporterIFC, wallElement.get_Geometry(geomOptions), Transform.Identity); if (boundingBoxRep != null) shapeReps.Add(boundingBoxRep); prodDefRep = IFCInstanceExporter.CreateProductDefinitionShape(file, null, null, shapeReps); return prodDefRep; }
private static void ExportAsMappedItem(ExporterIFC exporterIFC, Element element, IFCFile file, IFCExportType exportType, string ifcEnumType, IFCExtrusionCreationData extraParams, PlacementSetter setter, IFCAnyHandle localPlacementToUse, IFCAnyHandle productRepresentation, ProductWrapper productWrapper) { IFCAnyHandle ownerHistory = ExporterCacheManager.OwnerHistoryHandle; ElementId typeId = element.GetTypeId(); ElementType type = element.Document.GetElement(typeId) as ElementType; IFCAnyHandle styleHandle = null; if (type != null) { FamilyTypeInfo currentTypeInfo = ExporterCacheManager.TypeObjectsCache.Find(typeId, false, exportType); bool found = currentTypeInfo.IsValid(); if (!found) { string typeGUID = GUIDUtil.CreateGUID(type); string typeName = NamingUtil.GetIFCName(type); string typeObjectType = NamingUtil.CreateIFCObjectName(exporterIFC, type); string applicableOccurance = NamingUtil.GetObjectTypeOverride(type, typeObjectType); string typeDescription = NamingUtil.GetDescriptionOverride(type, null); string typeElemId = NamingUtil.CreateIFCElementId(type); HashSet<IFCAnyHandle> propertySetsOpt = new HashSet<IFCAnyHandle>(); IList<IFCAnyHandle> repMapListOpt = new List<IFCAnyHandle>(); styleHandle = FamilyExporterUtil.ExportGenericType(exporterIFC, exportType, ifcEnumType, typeGUID, typeName, typeDescription, applicableOccurance, propertySetsOpt, repMapListOpt, typeElemId, typeName, element, type); if (!IFCAnyHandleUtil.IsNullOrHasNoValue(styleHandle)) { currentTypeInfo.Style = styleHandle; ExporterCacheManager.TypeObjectsCache.Register(typeId, false, exportType, currentTypeInfo); } } else { styleHandle = currentTypeInfo.Style; } } string instanceGUID = GUIDUtil.CreateGUID(element); string instanceName = NamingUtil.GetIFCName(element); string objectType = NamingUtil.CreateIFCObjectName(exporterIFC, element); string instanceObjectType = NamingUtil.GetObjectTypeOverride(element, objectType); string instanceDescription = NamingUtil.GetDescriptionOverride(element, null); string instanceElemId = NamingUtil.CreateIFCElementId(element); string instanceTag = NamingUtil.GetTagOverride(element, NamingUtil.CreateIFCElementId(element)); bool roomRelated = !FamilyExporterUtil.IsDistributionFlowElementSubType(exportType); ElementId roomId = ElementId.InvalidElementId; if (roomRelated) { roomId = setter.UpdateRoomRelativeCoordinates(element, out localPlacementToUse); } IFCAnyHandle instanceHandle = null; // For MEP objects string exportEntityStr = exportType.ToString(); Common.Enums.IFCEntityType exportEntity; if (String.Compare(exportEntityStr.Substring(exportEntityStr.Length - 4), "Type", true) == 0) exportEntityStr = exportEntityStr.Substring(0, (exportEntityStr.Length - 4)); if (Enum.TryParse(exportEntityStr, out exportEntity)) { // For MEP object creation instanceHandle = IFCInstanceExporter.CreateGenericIFCEntity(exportEntity, file, instanceGUID, ownerHistory, instanceName, instanceDescription, instanceObjectType, localPlacementToUse, productRepresentation, instanceTag); } if (IFCAnyHandleUtil.IsNullOrHasNoValue(instanceHandle)) return; if (roomId != ElementId.InvalidElementId) { //exporterIFC.RelateSpatialElement(roomId, instanceHandle); ExporterCacheManager.SpaceInfoCache.RelateToSpace(roomId, instanceHandle); productWrapper.AddElement(element, instanceHandle, setter, extraParams, false); } else { productWrapper.AddElement(element, instanceHandle, setter, extraParams, true); } OpeningUtil.CreateOpeningsIfNecessary(instanceHandle, element, extraParams, null, exporterIFC, localPlacementToUse, setter, productWrapper); if (!IFCAnyHandleUtil.IsNullOrHasNoValue(styleHandle)) ExporterCacheManager.TypeRelationsCache.Add(styleHandle, instanceHandle); PropertyUtil.CreateInternalRevitPropertySets(exporterIFC, element, productWrapper.GetAllObjects()); ExporterCacheManager.MEPCache.Register(element, instanceHandle); // add to system export cache // SystemExporter.ExportSystem(exporterIFC, element, instanceHandle); }
/// <summary> /// Exports the top stories of a multistory staircase. /// </summary> /// <param name="exporterIFC">The ExporterIFC object.</param> /// <param name="stair">The stairs element.</param> /// <param name="numFlights">The number of flights for a multistory staircase.</param> /// <param name="stairHnd">The stairs container handle.</param> /// <param name="components">The components handles.</param> /// <param name="ecData">The extrusion creation data.</param> /// <param name="componentECData">The extrusion creation data for the components.</param> /// <param name="placementSetter">The placement setter.</param> /// <param name="productWrapper">The ProductWrapper.</param> public static void ExportMultistoryStair(ExporterIFC exporterIFC, Element stair, int numFlights, IFCAnyHandle stairHnd, IList<IFCAnyHandle> components, IList<IFCExtrusionCreationData> componentECData, PlacementSetter placementSetter, ProductWrapper productWrapper) { if (numFlights < 2) return; double heightNonScaled = GetStairsHeight(exporterIFC, stair); if (heightNonScaled < MathUtil.Eps()) return; if (IFCAnyHandleUtil.IsNullOrHasNoValue(stairHnd)) return; IFCAnyHandle localPlacement = IFCAnyHandleUtil.GetObjectPlacement(stairHnd); if (IFCAnyHandleUtil.IsNullOrHasNoValue(localPlacement)) return; IFCAnyHandle ownerHistory = exporterIFC.GetOwnerHistoryHandle(); IFCFile file = exporterIFC.GetFile(); IFCAnyHandle relPlacement = GeometryUtil.GetRelativePlacementFromLocalPlacement(localPlacement); IFCAnyHandle ptHnd = IFCAnyHandleUtil.GetLocation(relPlacement); IList<double> origCoords = IFCAnyHandleUtil.GetCoordinates(ptHnd); ICollection<ElementId> runIds = null; ICollection<ElementId> landingIds = null; ICollection<ElementId> supportIds = null; if (stair is Stairs) { Stairs stairAsStairs = stair as Stairs; runIds = stairAsStairs.GetStairsRuns(); landingIds = stairAsStairs.GetStairsLandings(); supportIds = stairAsStairs.GetStairsSupports(); } IList<IFCAnyHandle> stairLocalPlacementHnds = new List<IFCAnyHandle>(); IList<IFCLevelInfo> levelInfos = new List<IFCLevelInfo>(); for (int ii = 0; ii < numFlights - 1; ii++) { IFCAnyHandle newLevelHnd = null; // We are going to avoid internal scaling routines, and instead scale in .NET. double newOffsetUnscaled = 0.0; IFCLevelInfo currLevelInfo = placementSetter.GetOffsetLevelInfoAndHandle(heightNonScaled * (ii + 1), 1.0, stair.Document, out newLevelHnd, out newOffsetUnscaled); double newOffsetScaled = UnitUtil.ScaleLength(newOffsetUnscaled); levelInfos.Add(currLevelInfo); if (levelInfos[ii] == null) levelInfos[ii] = placementSetter.LevelInfo; XYZ orig; if (ptHnd.HasValue) { orig = new XYZ(origCoords[0], origCoords[1], newOffsetScaled); } else { orig = new XYZ(0.0, 0.0, newOffsetScaled); } stairLocalPlacementHnds.Add(ExporterUtil.CreateLocalPlacement(file, newLevelHnd, orig, null, null)); } IList<List<IFCAnyHandle>> newComponents = new List<List<IFCAnyHandle>>(); for (int ii = 0; ii < numFlights - 1; ii++) newComponents.Add(new List<IFCAnyHandle>()); int compIdx = 0; IEnumerator<ElementId> runIter = null; if (runIds != null) { runIter = runIds.GetEnumerator(); runIter.MoveNext(); } IEnumerator<ElementId> landingIter = null; if (landingIds != null) { landingIter = landingIds.GetEnumerator(); landingIter.MoveNext(); } IEnumerator<ElementId> supportIter = null; if (supportIds != null) { supportIter = supportIds.GetEnumerator(); supportIter.MoveNext(); } foreach (IFCAnyHandle component in components) { string componentName = IFCAnyHandleUtil.GetStringAttribute(component, "Name"); string componentDescription = IFCAnyHandleUtil.GetStringAttribute(component, "Description"); string componentObjectType = IFCAnyHandleUtil.GetStringAttribute(component, "ObjectType"); string componentElementTag = IFCAnyHandleUtil.GetStringAttribute(component, "Tag"); IFCAnyHandle componentProdRep = IFCAnyHandleUtil.GetInstanceAttribute(component, "Representation"); IList<string> localComponentNames = new List<string>(); IList<IFCAnyHandle> componentPlacementHnds = new List<IFCAnyHandle>(); IFCAnyHandle localLocalPlacement = IFCAnyHandleUtil.GetObjectPlacement(component); IFCAnyHandle localRelativePlacement = (localLocalPlacement == null) ? null : IFCAnyHandleUtil.GetInstanceAttribute(localLocalPlacement, "RelativePlacement"); bool isSubStair = component.IsSubTypeOf(IFCEntityType.IfcStair.ToString()); for (int ii = 0; ii < numFlights - 1; ii++) { localComponentNames.Add((componentName == null) ? (ii + 2).ToString() : (componentName + ":" + (ii + 2))); if (isSubStair) componentPlacementHnds.Add(ExporterUtil.CopyLocalPlacement(file, stairLocalPlacementHnds[ii])); else componentPlacementHnds.Add(IFCInstanceExporter.CreateLocalPlacement(file, stairLocalPlacementHnds[ii], localRelativePlacement)); } IList<IFCAnyHandle> localComponentHnds = new List<IFCAnyHandle>(); if (isSubStair) { string componentType = IFCAnyHandleUtil.GetEnumerationAttribute(component, "ShapeType"); string localStairType = GetIFCStairType(componentType); ElementId catId = CategoryUtil.GetSafeCategoryId(stair); for (int ii = 0; ii < numFlights - 1; ii++) { IFCAnyHandle representationCopy = ExporterUtil.CopyProductDefinitionShape(exporterIFC, stair, catId, componentProdRep); localComponentHnds.Add(IFCInstanceExporter.CreateStair(file, GUIDUtil.CreateGUID(), ownerHistory, localComponentNames[ii], componentDescription, componentObjectType, componentPlacementHnds[ii], representationCopy, componentElementTag, localStairType)); } } else if (IFCAnyHandleUtil.IsSubTypeOf(component, IFCEntityType.IfcStairFlight)) { Element runElem = (runIter == null) ? stair : stair.Document.GetElement(runIter.Current); Element runElemToUse = (runElem == null) ? stair : runElem; ElementId catId = CategoryUtil.GetSafeCategoryId(runElemToUse); int? numberOfRiser = IFCAnyHandleUtil.GetIntAttribute(component, "NumberOfRiser"); int? numberOfTreads = IFCAnyHandleUtil.GetIntAttribute(component, "NumberOfTreads"); double? riserHeight = IFCAnyHandleUtil.GetDoubleAttribute(component, "RiserHeight"); double? treadLength = IFCAnyHandleUtil.GetDoubleAttribute(component, "TreadLength"); for (int ii = 0; ii < numFlights - 1; ii++) { IFCAnyHandle representationCopy = ExporterUtil.CopyProductDefinitionShape(exporterIFC, runElemToUse, catId, componentProdRep); localComponentHnds.Add(IFCInstanceExporter.CreateStairFlight(file, GUIDUtil.CreateGUID(), ownerHistory, localComponentNames[ii], componentDescription, componentObjectType, componentPlacementHnds[ii], representationCopy, componentElementTag, numberOfRiser, numberOfTreads, riserHeight, treadLength, "NOTDEFINED")); } runIter.MoveNext(); } else if (IFCAnyHandleUtil.IsSubTypeOf(component, IFCEntityType.IfcSlab)) { Element landingElem = (landingIter == null) ? stair : stair.Document.GetElement(landingIter.Current); Element landingElemToUse = (landingElem == null) ? stair : landingElem; ElementId catId = CategoryUtil.GetSafeCategoryId(landingElemToUse); string componentType = IFCValidateEntry.GetValidIFCType(landingElemToUse, IFCAnyHandleUtil.GetEnumerationAttribute(component, "PredefinedType")); // IFCSlabType localLandingType = FloorExporter.GetIFCSlabType(componentType); for (int ii = 0; ii < numFlights - 1; ii++) { IFCAnyHandle representationCopy = ExporterUtil.CopyProductDefinitionShape(exporterIFC, landingElemToUse, catId, componentProdRep); localComponentHnds.Add(IFCInstanceExporter.CreateSlab(file, GUIDUtil.CreateGUID(), ownerHistory, localComponentNames[ii], componentDescription, componentObjectType, componentPlacementHnds[ii], representationCopy, componentElementTag, componentType)); } landingIter.MoveNext(); } else if (IFCAnyHandleUtil.IsSubTypeOf(component, IFCEntityType.IfcMember)) { Element supportElem = (supportIter == null) ? stair : stair.Document.GetElement(supportIter.Current); Element supportElemToUse = (supportElem == null) ? stair : supportElem; ElementId catId = CategoryUtil.GetSafeCategoryId(supportElemToUse); IFCAnyHandle memberType = (supportElemToUse != stair) ? GetMemberTypeHandle(exporterIFC, supportElemToUse) : null; for (int ii = 0; ii < numFlights - 1; ii++) { IFCAnyHandle representationCopy = ExporterUtil.CopyProductDefinitionShape(exporterIFC, supportElemToUse, catId, componentProdRep); localComponentHnds.Add(IFCInstanceExporter.CreateMember(file, GUIDUtil.CreateGUID(), ownerHistory, localComponentNames[ii], componentDescription, componentObjectType, componentPlacementHnds[ii], representationCopy, componentElementTag, "STRINGER")); if (memberType != null) ExporterCacheManager.TypeRelationsCache.Add(memberType, localComponentHnds[ii]); } supportIter.MoveNext(); } for (int ii = 0; ii < numFlights - 1; ii++) { if (localComponentHnds[ii] != null) { newComponents[ii].Add(localComponentHnds[ii]); productWrapper.AddElement(null, localComponentHnds[ii], levelInfos[ii], componentECData[compIdx], false); } } compIdx++; } // finally add a copy of the container. IList<IFCAnyHandle> stairCopyHnds = new List<IFCAnyHandle>(); for (int ii = 0; ii < numFlights - 1; ii++) { string stairName = IFCAnyHandleUtil.GetStringAttribute(stairHnd, "Name"); string stairObjectType = IFCAnyHandleUtil.GetStringAttribute(stairHnd, "ObjectType"); string stairDescription = IFCAnyHandleUtil.GetStringAttribute(stairHnd, "Description"); string stairElementTag = IFCAnyHandleUtil.GetStringAttribute(stairHnd, "Tag"); string stairTypeAsString = IFCAnyHandleUtil.GetEnumerationAttribute(stairHnd, "ShapeType"); string stairType = GetIFCStairType(stairTypeAsString); string containerStairName = stairName + ":" + (ii + 2); stairCopyHnds.Add(IFCInstanceExporter.CreateStair(file, GUIDUtil.CreateGUID(), ownerHistory, containerStairName, stairDescription, stairObjectType, stairLocalPlacementHnds[ii], null, stairElementTag, stairType)); productWrapper.AddElement(stair, stairCopyHnds[ii], levelInfos[ii], null, true); } for (int ii = 0; ii < numFlights - 1; ii++) { StairRampContainerInfo stairRampInfo = new StairRampContainerInfo(stairCopyHnds[ii], newComponents[ii], stairLocalPlacementHnds[ii]); ExporterCacheManager.StairRampContainerInfoCache.AppendStairRampContainerInfo(stair.Id, stairRampInfo); } }
/// <summary> /// Export the individual part (IfcBuildingElementPart). /// </summary> /// <param name="exporterIFC">The ExporterIFC object.</param> /// <param name="partElement">The part element to export.</param> /// <param name="geometryElement">The geometry of part.</param> /// <param name="productWrapper">The ProductWrapper object.</param> public static void ExportPart(ExporterIFC exporterIFC, Element partElement, ProductWrapper productWrapper, PlacementSetter placementSetter, IFCAnyHandle originalPlacement, IFCRange range, IFCExtrusionAxes ifcExtrusionAxes, Element hostElement, ElementId overrideLevelId, bool asBuildingElement) { if (!ElementFilteringUtil.IsElementVisible(partElement)) return; Part part = partElement as Part; if (part == null) return; PlacementSetter standalonePlacementSetter = null; bool standaloneExport = hostElement == null && !asBuildingElement; ElementId partExportLevel = null; if (standaloneExport || asBuildingElement) { partExportLevel = partElement.LevelId; } else { if (part.OriginalCategoryId != hostElement.Category.Id) return; partExportLevel = hostElement.LevelId; } if (overrideLevelId != null) partExportLevel = overrideLevelId; if (ExporterCacheManager.PartExportedCache.HasExported(partElement.Id, partExportLevel)) return; Options options = GeometryUtil.GetIFCExportGeometryOptions(); View ownerView = partElement.Document.GetElement(partElement.OwnerViewId) as View; if (ownerView != null) options.View = ownerView; GeometryElement geometryElement = partElement.get_Geometry(options); if (geometryElement == null) return; try { IFCFile file = exporterIFC.GetFile(); using (IFCTransaction transaction = new IFCTransaction(file)) { IFCAnyHandle partPlacement = null; if (standaloneExport || asBuildingElement) { Transform orientationTrf = Transform.Identity; standalonePlacementSetter = PlacementSetter.Create(exporterIFC, partElement, null, orientationTrf, partExportLevel); partPlacement = standalonePlacementSetter.LocalPlacement; } else { partPlacement = ExporterUtil.CreateLocalPlacement(file, originalPlacement, null); } bool validRange = (range != null && !MathUtil.IsAlmostZero(range.Start - range.End)); SolidMeshGeometryInfo solidMeshInfo; if (validRange) { solidMeshInfo = GeometryUtil.GetSplitClippedSolidMeshGeometry(geometryElement, range); if (solidMeshInfo.GetSolids().Count == 0 && solidMeshInfo.GetMeshes().Count == 0) return; } else { solidMeshInfo = GeometryUtil.GetSplitSolidMeshGeometry(geometryElement); } using (IFCExtrusionCreationData extrusionCreationData = new IFCExtrusionCreationData()) { extrusionCreationData.SetLocalPlacement(partPlacement); extrusionCreationData.ReuseLocalPlacement = false; extrusionCreationData.PossibleExtrusionAxes = ifcExtrusionAxes; IList<Solid> solids = solidMeshInfo.GetSolids(); IList<Mesh> meshes = solidMeshInfo.GetMeshes(); ElementId catId = CategoryUtil.GetSafeCategoryId(partElement); ElementId hostCatId = CategoryUtil.GetSafeCategoryId(hostElement); BodyData bodyData = null; BodyExporterOptions bodyExporterOptions = new BodyExporterOptions(true); if (solids.Count > 0 || meshes.Count > 0) { bodyData = BodyExporter.ExportBody(exporterIFC, partElement, catId, ElementId.InvalidElementId, solids, meshes, bodyExporterOptions, extrusionCreationData); } else { IList<GeometryObject> geomlist = new List<GeometryObject>(); geomlist.Add(geometryElement); bodyData = BodyExporter.ExportBody(exporterIFC, partElement, catId, ElementId.InvalidElementId, geomlist, bodyExporterOptions, extrusionCreationData); } IFCAnyHandle bodyRep = bodyData.RepresentationHnd; if (IFCAnyHandleUtil.IsNullOrHasNoValue(bodyRep)) { extrusionCreationData.ClearOpenings(); return; } IList<IFCAnyHandle> representations = new List<IFCAnyHandle>(); representations.Add(bodyRep); IFCAnyHandle boundingBoxRep = BoundingBoxExporter.ExportBoundingBox(exporterIFC, geometryElement, Transform.Identity); if (boundingBoxRep != null) representations.Add(boundingBoxRep); IFCAnyHandle prodRep = IFCInstanceExporter.CreateProductDefinitionShape(file, null, null, representations); IFCAnyHandle ownerHistory = exporterIFC.GetOwnerHistoryHandle(); string partGUID = GUIDUtil.CreateGUID(partElement); string partName = NamingUtil.GetNameOverride(partElement, NamingUtil.GetIFCName(partElement)); string partDescription = NamingUtil.GetDescriptionOverride(partElement, null); string partObjectType = NamingUtil.GetObjectTypeOverride(partElement, NamingUtil.CreateIFCObjectName(exporterIFC, partElement)); string partTag = NamingUtil.GetTagOverride(partElement, NamingUtil.CreateIFCElementId(partElement)); IFCAnyHandle ifcPart = null; if (!asBuildingElement) { ifcPart = IFCInstanceExporter.CreateBuildingElementPart(file, partGUID, ownerHistory, partName, partDescription, partObjectType, extrusionCreationData.GetLocalPlacement(), prodRep, partTag); } else { string ifcEnumType = null; IFCExportType exportType = ExporterUtil.GetExportType(exporterIFC, hostElement, out ifcEnumType); string defaultValue = null; // This replicates old functionality before IFC4 addition, where the default for slab was "FLOOR". // Really the export layer table should be fixed for this case. if (string.IsNullOrWhiteSpace(ifcEnumType) && hostCatId == new ElementId(BuiltInCategory.OST_Floors)) ifcEnumType = "FLOOR"; ifcEnumType = IFCValidateEntry.GetValidIFCType(hostElement, ifcEnumType, defaultValue); switch (exportType) { case IFCExportType.IfcColumnType: ifcPart = IFCInstanceExporter.CreateColumn(file, partGUID, ownerHistory, partName, partDescription, partObjectType, extrusionCreationData.GetLocalPlacement(), prodRep, partTag, ifcEnumType); break; case IFCExportType.IfcCovering: ifcPart = IFCInstanceExporter.CreateCovering(file, partGUID, ownerHistory, partName, partDescription, partObjectType, extrusionCreationData.GetLocalPlacement(), prodRep, partTag, ifcEnumType); break; case IFCExportType.IfcFooting: ifcPart = IFCInstanceExporter.CreateFooting(file, partGUID, ownerHistory, partName, partDescription, partObjectType, extrusionCreationData.GetLocalPlacement(), prodRep, partTag, ifcEnumType); break; case IFCExportType.IfcPile: ifcPart = IFCInstanceExporter.CreatePile(file, partGUID, ownerHistory, partName, partDescription, partObjectType, extrusionCreationData.GetLocalPlacement(), prodRep, partTag, ifcEnumType, null); break; case IFCExportType.IfcRoof: ifcPart = IFCInstanceExporter.CreateRoof(file, partGUID, ownerHistory, partName, partDescription, partObjectType, extrusionCreationData.GetLocalPlacement(), prodRep, partTag, ifcEnumType); break; case IFCExportType.IfcSlab: ifcPart = IFCInstanceExporter.CreateSlab(file, partGUID, ownerHistory, partName, partDescription, partObjectType, extrusionCreationData.GetLocalPlacement(), prodRep, partTag, ifcEnumType); break; case IFCExportType.IfcWall: ifcPart = IFCInstanceExporter.CreateWall(file, partGUID, ownerHistory, partName, partDescription, partObjectType, extrusionCreationData.GetLocalPlacement(), prodRep, partTag, ifcEnumType); break; default: ifcPart = IFCInstanceExporter.CreateBuildingElementProxy(file, partGUID, ownerHistory, partName, partDescription, partObjectType, extrusionCreationData.GetLocalPlacement(), prodRep, partTag, null); break; } } bool containedInLevel = (standaloneExport || asBuildingElement); PlacementSetter whichPlacementSetter = containedInLevel ? standalonePlacementSetter : placementSetter; productWrapper.AddElement(partElement, ifcPart, whichPlacementSetter, extrusionCreationData, containedInLevel); OpeningUtil.CreateOpeningsIfNecessary(ifcPart, partElement, extrusionCreationData, bodyData.OffsetTransform, exporterIFC, extrusionCreationData.GetLocalPlacement(), whichPlacementSetter, productWrapper); //Add the exported part to exported cache. TraceExportedParts(partElement, partExportLevel, standaloneExport || asBuildingElement ? ElementId.InvalidElementId : hostElement.Id); CategoryUtil.CreateMaterialAssociations(exporterIFC, ifcPart, bodyData.MaterialIds); transaction.Commit(); } } } finally { if (standalonePlacementSetter != null) standalonePlacementSetter.Dispose(); } }
/// <summary> /// Adds openings to an element. /// </summary> /// <param name="exporterIFC">The exporter.</param> /// <param name="elementHandle">The parent handle.</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, IFCAnyHandle elementHandle, Element element, Plane plane, double scaledWidth, IFCRange range, PlacementSetter setter, IFCAnyHandle localPlacement, ProductWrapper localWrapper) { IList<IFCAnyHandle> elementHandles = new List<IFCAnyHandle>(); elementHandles.Add(elementHandle); AddOpeningsToElement(exporterIFC, elementHandles, null, element, plane, scaledWidth, range, setter, localPlacement, localWrapper); }
/// <summary> /// Creates an opening from a solid. /// </summary> /// <param name="exporterIFC">The exporter.</param> /// <param name="hostObjHnd">The host object handle.</param> /// <param name="hostElement">The host element.</param> /// <param name="insertElement">The insert element.</param> /// <param name="openingGUID">The GUID for the opening, depending on how the opening is created.</param> /// <param name="solid">The solid.</param> /// <param name="scaledHostWidth">The scaled host width.</param> /// <param name="isRecess">True if it is recess.</param> /// <param name="extrusionCreationData">The extrusion creation data.</param> /// <param name="setter">The placement setter.</param> /// <param name="localWrapper">The product wrapper.</param> /// <returns>The created opening handle.</returns> static public IFCAnyHandle CreateOpening(ExporterIFC exporterIFC, IFCAnyHandle hostObjHnd, Element hostElement, Element insertElement, string openingGUID, Solid solid, double scaledHostWidth, bool isRecess, IFCExtrusionCreationData extrusionCreationData, PlacementSetter setter, ProductWrapper localWrapper) { IFCFile file = exporterIFC.GetFile(); ElementId catId = CategoryUtil.GetSafeCategoryId(insertElement); XYZ prepToWall; bool isLinearWall = GetOpeningDirection(hostElement, out prepToWall); if (isLinearWall) { extrusionCreationData.CustomAxis = prepToWall; extrusionCreationData.PossibleExtrusionAxes = IFCExtrusionAxes.TryCustom; } BodyExporterOptions bodyExporterOptions = new BodyExporterOptions(true); BodyData bodyData = BodyExporter.ExportBody(exporterIFC, insertElement, catId, ElementId.InvalidElementId, solid, bodyExporterOptions, extrusionCreationData); IFCAnyHandle openingRepHnd = bodyData.RepresentationHnd; if (IFCAnyHandleUtil.IsNullOrHasNoValue(openingRepHnd)) { extrusionCreationData.ClearOpenings(); return null; } IList<IFCAnyHandle> representations = new List<IFCAnyHandle>(); representations.Add(openingRepHnd); IFCAnyHandle prodRep = IFCInstanceExporter.CreateProductDefinitionShape(file, null, null, representations); IFCAnyHandle openingPlacement = extrusionCreationData.GetLocalPlacement(); IFCAnyHandle hostObjPlacementHnd = IFCAnyHandleUtil.GetObjectPlacement(hostObjHnd); Transform relTransform = ExporterIFCUtils.GetRelativeLocalPlacementOffsetTransform(openingPlacement, hostObjPlacementHnd); openingPlacement = ExporterUtil.CreateLocalPlacement(file, hostObjPlacementHnd, relTransform.Origin, relTransform.BasisZ, relTransform.BasisX); IFCAnyHandle ownerHistory = exporterIFC.GetOwnerHistoryHandle(); double scaledOpeningLength = extrusionCreationData.ScaledLength; string openingObjectType = "Opening"; if (!MathUtil.IsAlmostZero(scaledHostWidth) && !MathUtil.IsAlmostZero(scaledOpeningLength)) openingObjectType = scaledOpeningLength < (scaledHostWidth - MathUtil.Eps()) ? "Recess" : "Opening"; else openingObjectType = isRecess ? "Recess" : "Opening"; string openingName = NamingUtil.GetNameOverride(insertElement, null); if (string.IsNullOrEmpty(openingName)) { if (!IFCAnyHandleUtil.IsNullOrHasNoValue(hostObjHnd)) openingName = IFCAnyHandleUtil.GetStringAttribute(hostObjHnd, "Name"); else openingName = NamingUtil.GetNameOverride(hostElement, NamingUtil.CreateIFCObjectName(exporterIFC, hostElement)); } IFCAnyHandle openingHnd = IFCInstanceExporter.CreateOpeningElement(file, openingGUID, ownerHistory, openingName, null, openingObjectType, openingPlacement, prodRep, null); if (ExporterCacheManager.ExportOptionsCache.ExportBaseQuantities) PropertyUtil.CreateOpeningQuantities(exporterIFC, openingHnd, extrusionCreationData); if (localWrapper != null) { Element elementForProperties = null; if (GUIDUtil.IsGUIDFor(insertElement, openingGUID)) elementForProperties = insertElement; localWrapper.AddElement(insertElement, openingHnd, setter, extrusionCreationData, true); } string voidGuid = GUIDUtil.CreateGUID(); IFCInstanceExporter.CreateRelVoidsElement(file, voidGuid, ownerHistory, null, null, hostObjHnd, openingHnd); return openingHnd; }
/// <summary> /// Exports the top stories of a multistory ramp. /// </summary> /// <param name="exporterIFC">The ExporterIFC object.</param> /// <param name="ramp">The ramp element.</param> /// <param name="numFlights">The number of flights for a multistory ramp.</param> /// <param name="rampHnd">The stairs container handle.</param> /// <param name="components">The components handles.</param> /// <param name="ecData">The extrusion creation data.</param> /// <param name="componentECData">The extrusion creation data for the components.</param> /// <param name="placementSetter">The placement setter.</param> /// <param name="productWrapper">The ProductWrapper.</param> public static void ExportMultistoryRamp(ExporterIFC exporterIFC, Element ramp, int numFlights, IFCAnyHandle rampHnd, IList<IFCAnyHandle> components, IList<IFCExtrusionCreationData> componentECData, PlacementSetter placementSetter, ProductWrapper productWrapper) { if (numFlights < 2) return; double heightNonScaled = GetRampHeight(exporterIFC, ramp); if (heightNonScaled < MathUtil.Eps()) return; if (IFCAnyHandleUtil.IsNullOrHasNoValue(rampHnd)) return; IFCAnyHandle localPlacement = IFCAnyHandleUtil.GetObjectPlacement(rampHnd); if (IFCAnyHandleUtil.IsNullOrHasNoValue(localPlacement)) return; IFCAnyHandle ownerHistory = exporterIFC.GetOwnerHistoryHandle(); IFCFile file = exporterIFC.GetFile(); IFCAnyHandle relPlacement = GeometryUtil.GetRelativePlacementFromLocalPlacement(localPlacement); IFCAnyHandle ptHnd = IFCAnyHandleUtil.GetLocation(relPlacement); IList<double> origCoords = IFCAnyHandleUtil.GetCoordinates(ptHnd); IList<IFCAnyHandle> rampLocalPlacementHnds = new List<IFCAnyHandle>(); IList<IFCLevelInfo> levelInfos = new List<IFCLevelInfo>(); for (int ii = 0; ii < numFlights - 1; ii++) { IFCAnyHandle newLevelHnd = null; // We are going to avoid internal scaling routines, and instead scale in .NET. double newOffsetUnscaled = 0.0; IFCLevelInfo currLevelInfo = placementSetter.GetOffsetLevelInfoAndHandle(heightNonScaled * (ii + 1), 1.0, ramp.Document, out newLevelHnd, out newOffsetUnscaled); double newOffsetScaled = UnitUtil.ScaleLength(newOffsetUnscaled); levelInfos.Add(currLevelInfo); if (levelInfos[ii] == null) levelInfos[ii] = placementSetter.LevelInfo; XYZ orig; if (ptHnd.HasValue) { orig = new XYZ(origCoords[0], origCoords[1], newOffsetScaled); } else { orig = new XYZ(0.0, 0.0, newOffsetScaled); } rampLocalPlacementHnds.Add(ExporterUtil.CreateLocalPlacement(file, newLevelHnd, orig, null, null)); } IList<List<IFCAnyHandle>> newComponents = new List<List<IFCAnyHandle>>(); for (int ii = 0; ii < numFlights - 1; ii++) newComponents.Add(new List<IFCAnyHandle>()); int compIdx = 0; ElementId catId = CategoryUtil.GetSafeCategoryId(ramp); foreach (IFCAnyHandle component in components) { string componentName = IFCAnyHandleUtil.GetStringAttribute(component, "Name"); string componentDescription = IFCAnyHandleUtil.GetStringAttribute(component, "Description"); string componentObjectType = IFCAnyHandleUtil.GetStringAttribute(component, "ObjectType"); string componentElementTag = IFCAnyHandleUtil.GetStringAttribute(component, "Tag"); IFCAnyHandle componentProdRep = IFCAnyHandleUtil.GetInstanceAttribute(component, "Representation"); IList<string> localComponentNames = new List<string>(); IList<IFCAnyHandle> componentPlacementHnds = new List<IFCAnyHandle>(); IFCAnyHandle localLocalPlacement = IFCAnyHandleUtil.GetObjectPlacement(component); IFCAnyHandle localRelativePlacement = (localLocalPlacement == null) ? null : IFCAnyHandleUtil.GetInstanceAttribute(localLocalPlacement, "RelativePlacement"); bool isSubRamp = component.IsSubTypeOf(IFCEntityType.IfcRamp.ToString()); for (int ii = 0; ii < numFlights - 1; ii++) { localComponentNames.Add((componentName == null) ? (ii + 2).ToString() : (componentName + ":" + (ii + 2))); if (isSubRamp) componentPlacementHnds.Add(ExporterUtil.CopyLocalPlacement(file, rampLocalPlacementHnds[ii])); else componentPlacementHnds.Add(IFCInstanceExporter.CreateLocalPlacement(file, rampLocalPlacementHnds[ii], localRelativePlacement)); } IList<IFCAnyHandle> localComponentHnds = new List<IFCAnyHandle>(); if (isSubRamp) { string componentType = IFCAnyHandleUtil.GetEnumerationAttribute(component, ExporterCacheManager.ExportOptionsCache.ExportAs4 ? "PredefinedType" : "ShapeType"); string localRampType = GetIFCRampType(componentType); for (int ii = 0; ii < numFlights - 1; ii++) { IFCAnyHandle representationCopy = ExporterUtil.CopyProductDefinitionShape(exporterIFC, ramp, catId, componentProdRep); localComponentHnds.Add(IFCInstanceExporter.CreateRamp(file, GUIDUtil.CreateGUID(), ownerHistory, localComponentNames[ii], componentDescription, componentObjectType, componentPlacementHnds[ii], representationCopy, componentElementTag, localRampType)); } } else if (IFCAnyHandleUtil.IsSubTypeOf(component, IFCEntityType.IfcRampFlight)) { for (int ii = 0; ii < numFlights - 1; ii++) { IFCAnyHandle representationCopy = ExporterUtil.CopyProductDefinitionShape(exporterIFC, ramp, catId, componentProdRep); localComponentHnds.Add(IFCInstanceExporter.CreateRampFlight(file, GUIDUtil.CreateGUID(), ownerHistory, localComponentNames[ii], componentDescription, componentObjectType, componentPlacementHnds[ii], representationCopy, componentElementTag, "NOTDEFINED")); } } else if (IFCAnyHandleUtil.IsSubTypeOf(component, IFCEntityType.IfcSlab)) { string componentType = IFCAnyHandleUtil.GetEnumerationAttribute(component, "PredefinedType"); IFCSlabType localLandingType = FloorExporter.GetIFCSlabType(componentType); for (int ii = 0; ii < numFlights - 1; ii++) { IFCAnyHandle representationCopy = ExporterUtil.CopyProductDefinitionShape(exporterIFC, ramp, catId, componentProdRep); localComponentHnds.Add(IFCInstanceExporter.CreateSlab(file, GUIDUtil.CreateGUID(), ownerHistory, localComponentNames[ii], componentDescription, componentObjectType, componentPlacementHnds[ii], representationCopy, componentElementTag, localLandingType.ToString())); } } else if (IFCAnyHandleUtil.IsSubTypeOf(component, IFCEntityType.IfcMember)) { for (int ii = 0; ii < numFlights - 1; ii++) { IFCAnyHandle representationCopy = ExporterUtil.CopyProductDefinitionShape(exporterIFC, ramp, catId, componentProdRep); localComponentHnds.Add(IFCInstanceExporter.CreateMember(file, GUIDUtil.CreateGUID(), ownerHistory, localComponentNames[ii], componentDescription, componentObjectType, componentPlacementHnds[ii], representationCopy, componentElementTag, "STRINGER")); } } for (int ii = 0; ii < numFlights - 1; ii++) { if (localComponentHnds[ii] != null) { newComponents[ii].Add(localComponentHnds[ii]); productWrapper.AddElement(null, localComponentHnds[ii], levelInfos[ii], componentECData[compIdx], false); } } compIdx++; } // finally add a copy of the container. IList<IFCAnyHandle> rampCopyHnds = new List<IFCAnyHandle>(); for (int ii = 0; ii < numFlights - 1; ii++) { string rampName = IFCAnyHandleUtil.GetStringAttribute(rampHnd, "Name"); string rampObjectType = IFCAnyHandleUtil.GetStringAttribute(rampHnd, "ObjectType"); string rampDescription = IFCAnyHandleUtil.GetStringAttribute(rampHnd, "Description"); string rampElementTag = IFCAnyHandleUtil.GetStringAttribute(rampHnd, "Tag"); string rampTypeAsString = null; if (ExporterCacheManager.ExportOptionsCache.ExportAs4) rampTypeAsString = IFCAnyHandleUtil.GetEnumerationAttribute(rampHnd, "PredefinedType"); else rampTypeAsString = IFCAnyHandleUtil.GetEnumerationAttribute(rampHnd, "ShapeType"); string rampType = GetIFCRampType(rampTypeAsString); string containerRampName = rampName + ":" + (ii + 2); rampCopyHnds.Add(IFCInstanceExporter.CreateRamp(file, GUIDUtil.CreateGUID(), ownerHistory, containerRampName, rampDescription, rampObjectType, rampLocalPlacementHnds[ii], null, rampElementTag, rampType)); productWrapper.AddElement(ramp, rampCopyHnds[ii], levelInfos[ii], null, true); } for (int ii = 0; ii < numFlights - 1; ii++) { StairRampContainerInfo stairRampInfo = new StairRampContainerInfo(rampCopyHnds[ii], newComponents[ii], rampLocalPlacementHnds[ii]); ExporterCacheManager.StairRampContainerInfoCache.AppendStairRampContainerInfo(ramp.Id, stairRampInfo); } }
/// <summary> /// Add a generic element to the wrapper, with associated setter and extrusion data information, and create associated internal property sets if option is set. /// </summary> /// <param name="element">The element.</param> /// <param name="handle">The element handle.</param> /// <param name="setter">The placement setter.</param> /// <param name="data">The extrusion creation data (can be null.)</param> /// <param name="relateToLevel">Relate to the level in the setter, or not.</param> public void AddElement(Element element, IFCAnyHandle handle, PlacementSetter setter, IFCExtrusionCreationData data, bool relateToLevel) { // There is a bug in the internal AddElement that requires us to do a levelInfo null check here. IFCLevelInfo levelInfo = setter.LevelInfo; bool actuallyRelateToLevel = relateToLevel && (levelInfo != null); m_InternalWrapper.AddElement(handle, levelInfo, data, actuallyRelateToLevel); if (levelInfo == null && relateToLevel) ExporterCacheManager.LevelInfoCache.OrphanedElements.Add(handle); RegisterHandleWithElement(element, handle); }
/// <summary> /// Add a generic element to the wrapper, with associated setter and extrusion data information, and create associated internal property sets if option is set. /// </summary> /// <param name="element">The element.</param> /// <param name="handle">The element handle.</param> /// <param name="setter">The placement setter.</param> /// <param name="data">The extrusion creation data (can be null.)</param> /// <param name="relateToLevel">Relate to the level in the setter, or not.</param> public void AddElement(Element element, IFCAnyHandle handle, PlacementSetter setter, IFCExtrusionCreationData data, bool relateToLevel) { m_InternalWrapper.AddElement(handle, setter.LevelInfo, data, relateToLevel); RegisterHandleWithElement(element, handle); }
/// <summary> /// Gets the offset of the space boundary. /// </summary> /// <param name="setter">The placement settter.</param> /// <returns>The offset.</returns> static XYZ GetSpaceBoundaryOffset(PlacementSetter setter) { IFCAnyHandle localPlacement = setter.LocalPlacement; double zOffset = setter.Offset; IFCAnyHandle relPlacement = GeometryUtil.GetRelativePlacementFromLocalPlacement(localPlacement); if (!IFCAnyHandleUtil.IsNullOrHasNoValue(relPlacement)) { IFCAnyHandle ptHnd = IFCAnyHandleUtil.GetLocation(relPlacement); if (!IFCAnyHandleUtil.IsNullOrHasNoValue(ptHnd)) { IList<double> addToCoords = IFCAnyHandleUtil.GetCoordinates(ptHnd); return new XYZ(addToCoords[0], addToCoords[1], addToCoords[2] + zOffset); } } return new XYZ(0, 0, zOffset); }
private static IFCAnyHandle TryToCreateAsExtrusion(ExporterIFC exporterIFC, Wall wallElement, IList<IList<IFCConnectedWallData>> connectedWalls, IList<Solid> solids, IList<Mesh> meshes, double baseWallElevation, ElementId catId, Curve baseCurve, Curve trimmedCurve, Plane wallLCS, double scaledDepth, IFCRange zSpan, IFCRange range, PlacementSetter setter, out IList<IFCExtrusionData> cutPairOpenings, out bool isCompletelyClipped, out double scaledFootprintArea, out double scaledLength) { cutPairOpenings = new List<IFCExtrusionData>(); IFCAnyHandle bodyRep; scaledFootprintArea = 0; double unscaledLength = trimmedCurve != null ? trimmedCurve.Length : 0; scaledLength = UnitUtil.ScaleLength(unscaledLength); XYZ localOrig = wallLCS.Origin; // Check to see if the wall has geometry given the specified range. if (!WallHasGeometryToExport(wallElement, solids, meshes, range, out isCompletelyClipped)) return null; // This is our major check here that goes into internal code. If we have enough information to faithfully reproduce // the wall as an extrusion with clippings and openings, we will continue. Otherwise, export it as a BRep. if (!CanExportWallGeometryAsExtrusion(wallElement, range)) return null; // extrusion direction. XYZ extrusionDir = GetWallHeightDirection(wallElement); // create extrusion boundary. bool alwaysThickenCurve = IsWallBaseRectangular(wallElement, trimmedCurve); double unscaledWidth = wallElement.Width; IList<CurveLoop> boundaryLoops = GetBoundaryLoopsFromWall(exporterIFC, wallElement, alwaysThickenCurve, trimmedCurve, unscaledWidth); if (boundaryLoops == null || boundaryLoops.Count == 0) return null; double fullUnscaledLength = baseCurve.Length; double unscaledFootprintArea = ExporterIFCUtils.ComputeAreaOfCurveLoops(boundaryLoops); scaledFootprintArea = UnitUtil.ScaleArea(unscaledFootprintArea); // We are going to do a little sanity check here. If the scaledFootprintArea is significantly less than the // width * length of the wall footprint, we probably calculated the area wrong, and will abort. // This could occur because of a door or window that cuts a corner of the wall (i.e., has no wall material on one side). // We want the scaledFootprintArea to be at least (95% of approximateBaseArea - 2 * side wall area). // The "side wall area" is an approximate value that takes into account potential wall joins. // This prevents us from doing extra work for many small walls because of joins. We'll allow 1' (~30 cm) per side for this. double approximateUnscaledBaseArea = unscaledWidth * fullUnscaledLength; if (unscaledFootprintArea < (approximateUnscaledBaseArea * .95 - 2 * unscaledWidth)) { // Can't handle the case where we don't have a simple extrusion to begin with. if (!alwaysThickenCurve) return null; boundaryLoops = GetBoundaryLoopsFromBaseCurve(wallElement, connectedWalls, baseCurve, trimmedCurve, unscaledWidth, scaledDepth); if (boundaryLoops == null || boundaryLoops.Count == 0) return null; } // origin gets scaled later. double baseWallZOffset = localOrig[2] - ((range == null) ? baseWallElevation : Math.Min(range.Start, baseWallElevation)); XYZ modifiedSetterOffset = new XYZ(0, 0, setter.Offset + baseWallZOffset); IFCAnyHandle baseBodyItemHnd = ExtrusionExporter.CreateExtrudedSolidFromCurveLoop(exporterIFC, null, boundaryLoops, wallLCS, extrusionDir, scaledDepth); if (IFCAnyHandleUtil.IsNullOrHasNoValue(baseBodyItemHnd)) return null; IFCAnyHandle bodyItemHnd = AddClippingsToBaseExtrusion(exporterIFC, wallElement, modifiedSetterOffset, range, zSpan, baseBodyItemHnd, out cutPairOpenings); if (IFCAnyHandleUtil.IsNullOrHasNoValue(bodyItemHnd)) return null; bool hasClipping = bodyItemHnd.Id != baseBodyItemHnd.Id; ElementId matId = HostObjectExporter.GetFirstLayerMaterialId(wallElement); IFCAnyHandle styledItemHnd = BodyExporter.CreateSurfaceStyleForRepItem(exporterIFC, wallElement.Document, baseBodyItemHnd, matId); HashSet<IFCAnyHandle> bodyItems = new HashSet<IFCAnyHandle>(); bodyItems.Add(bodyItemHnd); // Check whether wall has opening. If it has, exporting it in the Reference View will need to be in a tessellated geometry that includes the opening cut IList<IFCOpeningData> openingDataList = ExporterIFCUtils.GetOpeningData(exporterIFC, wallElement, wallLCS, range); bool wallHasOpening = openingDataList.Count > 0; BodyExporterOptions options = new BodyExporterOptions(true); IFCAnyHandle contextOfItemsBody = exporterIFC.Get3DContextHandle("Body"); if (!hasClipping) { // Check whether wall has opening. If it has, exporting it in Reference View will need to be in a tesselated geometry that includes the opening cut if (ExporterUtil.IsReferenceView() && wallHasOpening) { List<GeometryObject> geomList = new List<GeometryObject>(); bodyItems.Clear(); // Since we will change the geometry, clear existing extrusion data first if (solids.Count > 0) foreach (GeometryObject solid in solids) geomList.Add(solid); if (meshes.Count > 0) foreach (GeometryObject mesh in meshes) geomList.Add(mesh); foreach (GeometryObject geom in geomList) { IFCAnyHandle triangulatedBodyItem = BodyExporter.ExportBodyAsTriangulatedFaceSet(exporterIFC, wallElement, options, geom); if (!IFCAnyHandleUtil.IsNullOrHasNoValue(triangulatedBodyItem)) bodyItems.Add(triangulatedBodyItem); } bodyRep = RepresentationUtil.CreateTessellatedRep(exporterIFC, wallElement, catId, contextOfItemsBody, bodyItems, null); } else bodyRep = RepresentationUtil.CreateSweptSolidRep(exporterIFC, wallElement, catId, contextOfItemsBody, bodyItems, null); } else { // Create TessellatedRep geometry if it is Reference View. if (ExporterUtil.IsReferenceView()) { List<GeometryObject> geomList = new List<GeometryObject>(); // The native function AddClippingsToBaseExtrusion will create the IfcBooleanClippingResult entity and therefore here we need to delete it foreach (IFCAnyHandle item in bodyItems) { item.Dispose(); //Still DOES NOT work, the IfcBooleanClippingResult is still orphaned in the IFC file! } bodyItems.Clear(); // Since we will change the geometry, clear existing extrusion data first if (solids.Count > 0) foreach (GeometryObject solid in solids) geomList.Add(solid); if (meshes.Count > 0) foreach (GeometryObject mesh in meshes) geomList.Add(mesh); foreach (GeometryObject geom in geomList) { IFCAnyHandle triangulatedBodyItem = BodyExporter.ExportBodyAsTriangulatedFaceSet(exporterIFC, wallElement, options, geom); if (!IFCAnyHandleUtil.IsNullOrHasNoValue(triangulatedBodyItem)) bodyItems.Add(triangulatedBodyItem); } bodyRep = RepresentationUtil.CreateTessellatedRep(exporterIFC, wallElement, catId, contextOfItemsBody, bodyItems, null); } else bodyRep = RepresentationUtil.CreateClippingRep(exporterIFC, wallElement, catId, contextOfItemsBody, bodyItems); } return bodyRep; }
/// <summary> /// Creates a new IfcAnnotation object. /// </summary> /// <param name="exporterIFC">The exporter.</param> /// <param name="curveElement">The curve element.</param> /// <param name="categoryId">The category id.</param> /// <param name="sketchPlaneId">The sketch plane id.</param> /// <param name="refPlane">The reference plane.</param> /// <param name="curveStyle">The curve style.</param> /// <param name="placementSetter">The placemenet setter.</param> /// <param name="localPlacement">The local placement.</param> /// <param name="repItemHnd">The representation item.</param> /// <returns>The handle.</returns> static IFCAnyHandle CreateCurveAnnotation(ExporterIFC exporterIFC, Element curveElement, ElementId categoryId, ElementId sketchPlaneId, Plane refPlane, IFCAnyHandle curveStyle, PlacementSetter placementSetter, IFCAnyHandle localPlacement, IFCAnyHandle repItemHnd) { HashSet<IFCAnyHandle> bodyItems = new HashSet<IFCAnyHandle>(); bodyItems.Add(repItemHnd); IFCAnyHandle bodyRepHnd = RepresentationUtil.CreateAnnotationSetRep(exporterIFC, curveElement, categoryId, exporterIFC.Get2DContextHandle(), bodyItems); if (IFCAnyHandleUtil.IsNullOrHasNoValue(bodyRepHnd)) throw new Exception("Failed to create shape representation."); List<IFCAnyHandle> shapes = new List<IFCAnyHandle>(); shapes.Add(bodyRepHnd); IFCFile file = exporterIFC.GetFile(); IFCAnyHandle prodShapeHnd = IFCInstanceExporter.CreateProductDefinitionShape(file, null, null, shapes); XYZ xDir = refPlane.XVec; XYZ zDir = refPlane.Normal; XYZ origin = refPlane.Origin; // subtract out level origin if we didn't already before. IFCLevelInfo levelInfo = placementSetter.LevelInfo; if (levelInfo != null && !MathUtil.IsAlmostEqual(zDir.Z, 1.0)) { zDir -= new XYZ(0, 0, levelInfo.Elevation); } origin = UnitUtil.ScaleLength(origin); IFCAnyHandle relativePlacement = ExporterUtil.CreateAxis(file, origin, zDir, xDir); GeometryUtil.SetRelativePlacement(localPlacement, relativePlacement); IFCAnyHandle annotation = IFCInstanceExporter.CreateAnnotation(file, GUIDUtil.CreateGUID(), exporterIFC.GetOwnerHistoryHandle(), null, null, null, localPlacement, prodShapeHnd); return annotation; }
private static IFCAnyHandle TryToCreateAsExtrusion(ExporterIFC exporterIFC, Wall wallElement, IList<IList<IFCConnectedWallData>> connectedWalls, IList<Solid> solids, IList<Mesh> meshes, double baseWallElevation, ElementId catId, Curve baseCurve, Curve trimmedCurve, Plane plane, double scaledDepth, IFCRange zSpan, IFCRange range, PlacementSetter setter, out IList<IFCExtrusionData> cutPairOpenings, out bool isCompletelyClipped, out double scaledFootprintArea, out double scaledLength) { cutPairOpenings = new List<IFCExtrusionData>(); IFCAnyHandle bodyRep; scaledFootprintArea = 0; double unscaledLength = trimmedCurve != null ? trimmedCurve.Length : 0; scaledLength = UnitUtil.ScaleLength(unscaledLength); XYZ localOrig = plane.Origin; // Check to see if the wall has geometry given the specified range. if (!WallHasGeometryToExport(wallElement, solids, meshes, range, out isCompletelyClipped)) return null; // This is our major check here that goes into internal code. If we have enough information to faithfully reproduce // the wall as an extrusion with clippings and openings, we will continue. Otherwise, export it as a BRep. if (!CanExportWallGeometryAsExtrusion(wallElement, range)) return null; // extrusion direction. XYZ extrusionDir = GetWallHeightDirection(wallElement); // create extrusion boundary. bool alwaysThickenCurve = IsWallBaseRectangular(wallElement, trimmedCurve); double unscaledWidth = wallElement.Width; IList<CurveLoop> boundaryLoops = GetBoundaryLoopsFromWall(exporterIFC, wallElement, alwaysThickenCurve, trimmedCurve, unscaledWidth); if (boundaryLoops == null || boundaryLoops.Count == 0) return null; double fullUnscaledLength = baseCurve.Length; double unscaledFootprintArea = ExporterIFCUtils.ComputeAreaOfCurveLoops(boundaryLoops); scaledFootprintArea = UnitUtil.ScaleArea(unscaledFootprintArea); // We are going to do a little sanity check here. If the scaledFootprintArea is significantly less than the // width * length of the wall footprint, we probably calculated the area wrong, and will abort. // This could occur because of a door or window that cuts a corner of the wall (i.e., has no wall material on one side). // We want the scaledFootprintArea to be at least (95% of approximateBaseArea - 2 * side wall area). // The "side wall area" is an approximate value that takes into account potential wall joins. // This prevents us from doing extra work for many small walls because of joins. We'll allow 1' (~30 cm) per side for this. double approximateUnscaledBaseArea = unscaledWidth * fullUnscaledLength; if (unscaledFootprintArea < (approximateUnscaledBaseArea * .95 - 2 * unscaledWidth)) { // Can't handle the case where we don't have a simple extrusion to begin with. if (!alwaysThickenCurve) return null; boundaryLoops = GetBoundaryLoopsFromBaseCurve(wallElement, connectedWalls, baseCurve, trimmedCurve, unscaledWidth, scaledDepth); if (boundaryLoops == null || boundaryLoops.Count == 0) return null; } // origin gets scaled later. XYZ setterOffset = new XYZ(0, 0, setter.Offset + (localOrig[2] - baseWallElevation)); IFCAnyHandle baseBodyItemHnd = ExtrusionExporter.CreateExtrudedSolidFromCurveLoop(exporterIFC, null, boundaryLoops, plane, extrusionDir, scaledDepth); if (IFCAnyHandleUtil.IsNullOrHasNoValue(baseBodyItemHnd)) return null; IFCAnyHandle bodyItemHnd = AddClippingsToBaseExtrusion(exporterIFC, wallElement, setterOffset, range, zSpan, baseBodyItemHnd, out cutPairOpenings); if (IFCAnyHandleUtil.IsNullOrHasNoValue(bodyItemHnd)) return null; ElementId matId = HostObjectExporter.GetFirstLayerMaterialId(wallElement); IFCAnyHandle styledItemHnd = BodyExporter.CreateSurfaceStyleForRepItem(exporterIFC, wallElement.Document, baseBodyItemHnd, matId); HashSet<IFCAnyHandle> bodyItems = new HashSet<IFCAnyHandle>(); bodyItems.Add(bodyItemHnd); IFCAnyHandle contextOfItemsBody = exporterIFC.Get3DContextHandle("Body"); if (baseBodyItemHnd.Id == bodyItemHnd.Id) bodyRep = RepresentationUtil.CreateSweptSolidRep(exporterIFC, wallElement, catId, contextOfItemsBody, bodyItems, null); else bodyRep = RepresentationUtil.CreateClippingRep(exporterIFC, wallElement, catId, contextOfItemsBody, bodyItems); return bodyRep; }