/// <summary> /// Exports a FabricArea as an IfcGroup. There is no geometry to export. /// </summary> /// <param name="exporterIFC">The ExporterIFC object.</param> /// <param name="element">The element.</param> /// <param name="productWrapper">The ProductWrapper.</param> /// <returns>True if exported successfully, false otherwise.</returns> public static bool ExportFabricArea(ExporterIFC exporterIFC, Element element, ProductWrapper productWrapper) { if (element == null) return false; HashSet<IFCAnyHandle> fabricSheetHandles = null; if (!ExporterCacheManager.FabricAreaHandleCache.TryGetValue(element.Id, out fabricSheetHandles)) return false; if (fabricSheetHandles == null || fabricSheetHandles.Count == 0) return false; IFCFile file = exporterIFC.GetFile(); using (IFCTransaction tr = new IFCTransaction(file)) { string guid = GUIDUtil.CreateGUID(element); IFCAnyHandle ownerHistory = exporterIFC.GetOwnerHistoryHandle(); string revitObjectType = exporterIFC.GetFamilyName(); string name = NamingUtil.GetNameOverride(element, revitObjectType); string description = NamingUtil.GetDescriptionOverride(element, null); string objectType = NamingUtil.GetObjectTypeOverride(element, revitObjectType); IFCAnyHandle fabricArea = IFCInstanceExporter.CreateGroup(file, guid, ownerHistory, name, description, objectType); productWrapper.AddElement(element, fabricArea); IFCInstanceExporter.CreateRelAssignsToGroup(file, GUIDUtil.CreateGUID(), ownerHistory, null, null, fabricSheetHandles, null, fabricArea); tr.Commit(); return true; } }
/// <summary> /// Exports a ceiling to IFC covering. /// </summary> /// <param name="exporterIFC"> /// The ExporterIFC object. /// </param> /// <param name="ceiling"> /// The ceiling element to be exported. /// </param> /// <param name="geomElement"> /// The geometry element. /// </param> /// <param name="productWrapper"> /// The ProductWrapper. /// </param> public static void ExportCeilingElement(ExporterIFC exporterIFC, Ceiling ceiling, GeometryElement geomElement, ProductWrapper productWrapper) { string ifcEnumType = ExporterUtil.GetIFCTypeFromExportTable(exporterIFC, ceiling); if (String.IsNullOrEmpty(ifcEnumType)) ifcEnumType = "CEILING"; ExportCovering(exporterIFC, ceiling, geomElement, ifcEnumType, productWrapper); }
/// <summary> /// Exports a hosted weep. /// </summary> /// <param name="exporterIFC">The ExporterIFC object.</param> /// <param name="hostedSweep">The hosted sweep element.</param> /// <param name="geometryElement">The geometry element.</param> /// <param name="productWrapper">The ProductWrapper.</param> public static void Export(ExporterIFC exporterIFC, HostedSweep hostedSweep, GeometryElement geometryElement, ProductWrapper productWrapper) { ElementId catId = CategoryUtil.GetSafeCategoryId(hostedSweep); if (catId == new ElementId(BuiltInCategory.OST_Gutter)) ExportGutter(exporterIFC, hostedSweep, geometryElement, productWrapper); else ProxyElementExporter.Export(exporterIFC, hostedSweep, geometryElement, productWrapper); }
/// <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> /// Exports a Rebar, AreaReinforcement or PathReinforcement to IFC ReinforcingBar. /// </summary> /// <param name="exporterIFC">The exporter.</param> /// <param name="element">The element.</param> /// <param name="productWrapper">The product wrapper.</param> public static void Export(ExporterIFC exporterIFC, Element element, ProductWrapper productWrapper) { ISet<IFCAnyHandle> createdRebars = null; if (element is Rebar) { ExportRebar(exporterIFC, element, productWrapper); } else if (element is AreaReinforcement) { AreaReinforcement areaReinforcement = element as AreaReinforcement; IList<ElementId> rebarIds = areaReinforcement.GetRebarInSystemIds(); Document doc = areaReinforcement.Document; foreach (ElementId id in rebarIds) { Element rebarInSystem = doc.GetElement(id); createdRebars = ExportRebar(exporterIFC, rebarInSystem, productWrapper); } } else if (element is PathReinforcement) { PathReinforcement pathReinforcement = element as PathReinforcement; IList<ElementId> rebarIds = pathReinforcement.GetRebarInSystemIds(); Document doc = pathReinforcement.Document; foreach (ElementId id in rebarIds) { Element rebarInSystem = doc.GetElement(id); createdRebars = ExportRebar(exporterIFC, rebarInSystem, productWrapper); } } if (createdRebars != null && createdRebars.Count > 1) { IFCFile file = exporterIFC.GetFile(); using (IFCTransaction tr = new IFCTransaction(file)) { string guid = GUIDUtil.CreateGUID(element); IFCAnyHandle ownerHistory = exporterIFC.GetOwnerHistoryHandle(); string revitObjectType = exporterIFC.GetFamilyName(); string name = NamingUtil.GetNameOverride(element, revitObjectType); string description = NamingUtil.GetDescriptionOverride(element, null); string objectType = NamingUtil.GetObjectTypeOverride(element, revitObjectType); IFCAnyHandle rebarGroup = IFCInstanceExporter.CreateGroup(file, guid, ownerHistory, name, description, objectType); productWrapper.AddElement(element, rebarGroup); IFCInstanceExporter.CreateRelAssignsToGroup(file, GUIDUtil.CreateGUID(), ownerHistory, null, null, createdRebars, null, rebarGroup); tr.Commit(); } } }
/// <summary> /// Exports an element as a covering of type insulation. /// </summary> /// <param name="exporterIFC">The ExporterIFC object.</param> /// <param name="element">The element.</param> /// <param name="geometryElement">The geometry element.</param> /// <param name="productWrapper">The ProductWrapper.</param> /// <returns>True if exported successfully, false otherwise.</returns> public static bool ExportDuctLining(ExporterIFC exporterIFC, Element element, GeometryElement geometryElement, ProductWrapper productWrapper) { if (element == null || geometryElement == null) return false; IFCFile file = exporterIFC.GetFile(); using (IFCTransaction tr = new IFCTransaction(file)) { using (PlacementSetter placementSetter = PlacementSetter.Create(exporterIFC, element)) { using (IFCExtrusionCreationData ecData = new IFCExtrusionCreationData()) { ecData.SetLocalPlacement(placementSetter.LocalPlacement); ElementId categoryId = CategoryUtil.GetSafeCategoryId(element); BodyExporterOptions bodyExporterOptions = new BodyExporterOptions(true); IFCAnyHandle representation = RepresentationUtil.CreateAppropriateProductDefinitionShape(exporterIFC, element, categoryId, geometryElement, bodyExporterOptions, null, ecData, true); if (IFCAnyHandleUtil.IsNullOrHasNoValue(representation)) { ecData.ClearOpenings(); return false; } string guid = GUIDUtil.CreateGUID(element); IFCAnyHandle ownerHistory = exporterIFC.GetOwnerHistoryHandle(); string revitObjectType = exporterIFC.GetFamilyName(); string name = NamingUtil.GetNameOverride(element, revitObjectType); string description = NamingUtil.GetDescriptionOverride(element, null); string objectType = NamingUtil.GetObjectTypeOverride(element, revitObjectType); IFCAnyHandle localPlacement = ecData.GetLocalPlacement(); string elementTag = NamingUtil.GetTagOverride(element, NamingUtil.CreateIFCElementId(element)); IFCAnyHandle ductLining = IFCInstanceExporter.CreateCovering(file, guid, ownerHistory, name, description, objectType, localPlacement, representation, elementTag, "Wrapping"); ExporterCacheManager.ElementToHandleCache.Register(element.Id, ductLining); productWrapper.AddElement(element, ductLining, placementSetter.LevelInfo, ecData, true); ElementId matId = BodyExporter.GetBestMaterialIdFromGeometryOrParameter(geometryElement, exporterIFC, element); CategoryUtil.CreateMaterialAssociation(exporterIFC, ductLining, matId); } } tr.Commit(); return true; } }
/// <summary> /// Exports a wall swepp. /// </summary> /// <param name="exporterIFC">The ExporterIFC object.</param> /// <param name="wallSweep">The WallSweep.</param> /// <param name="geometryElement">The geometry element.</param> /// <param name="productWrapper">The ProductWrapper.</param> public static void Export(ExporterIFC exporterIFC, WallSweep wallSweep, GeometryElement geometryElement, ProductWrapper productWrapper) { WallSweepInfo wallSweepInfo = wallSweep.GetWallSweepInfo(); //Reveals are exported as openings with wall exporter. if (wallSweepInfo.WallSweepType == WallSweepType.Reveal) return; if (!ProxyElementExporter.Export(exporterIFC, wallSweep, geometryElement, productWrapper)) return; HostObjectExporter.ExportHostObjectMaterials(exporterIFC, wallSweep, productWrapper.GetAnElement(), geometryElement, productWrapper, ElementId.InvalidElementId, Toolkit.IFCLayerSetDirection.Axis2, null); }
/// <summary> /// Exports an element as building element proxy. /// </summary> /// <remarks> /// This function is called from the Export function, but can also be called directly if you do not /// want CreateInternalPropertySets to be called. /// </remarks> /// <param name="exporterIFC">The ExporterIFC object.</param> /// <param name="element">The element.</param> /// <param name="geometryElement">The geometry element.</param> /// <param name="productWrapper">The ProductWrapper.</param> /// <returns>The handle if created, null otherwise.</returns> public static IFCAnyHandle ExportBuildingElementProxy(ExporterIFC exporterIFC, Element element, GeometryElement geometryElement, ProductWrapper productWrapper) { if (element == null || geometryElement == null) return null; IFCFile file = exporterIFC.GetFile(); IFCAnyHandle buildingElementProxy = null; using (IFCTransaction tr = new IFCTransaction(file)) { using (PlacementSetter placementSetter = PlacementSetter.Create(exporterIFC, element)) { using (IFCExtrusionCreationData ecData = new IFCExtrusionCreationData()) { ecData.SetLocalPlacement(placementSetter.LocalPlacement); ElementId categoryId = CategoryUtil.GetSafeCategoryId(element); BodyExporterOptions bodyExporterOptions = new BodyExporterOptions(true); IFCAnyHandle representation = RepresentationUtil.CreateAppropriateProductDefinitionShape(exporterIFC, element, categoryId, geometryElement, bodyExporterOptions, null, ecData, true); if (IFCAnyHandleUtil.IsNullOrHasNoValue(representation)) { ecData.ClearOpenings(); return null; } string guid = GUIDUtil.CreateGUID(element); IFCAnyHandle ownerHistory = ExporterCacheManager.OwnerHistoryHandle; string revitObjectType = exporterIFC.GetFamilyName(); string name = NamingUtil.GetNameOverride(element, revitObjectType); string description = NamingUtil.GetDescriptionOverride(element, null); string objectType = NamingUtil.GetObjectTypeOverride(element, revitObjectType); IFCAnyHandle localPlacement = ecData.GetLocalPlacement(); string elementTag = NamingUtil.GetTagOverride(element, NamingUtil.CreateIFCElementId(element)); buildingElementProxy = IFCInstanceExporter.CreateBuildingElementProxy(file, guid, ownerHistory, name, description, objectType, localPlacement, representation, elementTag, null); productWrapper.AddElement(element, buildingElementProxy, placementSetter.LevelInfo, ecData, true); } tr.Commit(); } } return buildingElementProxy; }
/// <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> /// Exports an element as a zone. /// </summary> /// <param name="exporterIFC">The ExporterIFC object.</param> /// <param name="element">The element.</param> /// <param name="productWrapper">The ProductWrapper.</param> public static void ExportZone(ExporterIFC exporterIFC, Zone element, ProductWrapper productWrapper) { if (element == null) return; HashSet<IFCAnyHandle> spaceHnds = new HashSet<IFCAnyHandle>(); SpaceSet spaces = element.Spaces; foreach (Space space in spaces) { if (space == null) continue; IFCAnyHandle spaceHnd = ExporterCacheManager.SpaceInfoCache.FindSpaceHandle(space.Id); if (!IFCAnyHandleUtil.IsNullOrHasNoValue(spaceHnd)) spaceHnds.Add(spaceHnd); } if (spaceHnds.Count == 0) return; IFCFile file = exporterIFC.GetFile(); using (IFCTransaction tr = new IFCTransaction(file)) { string guid = GUIDUtil.CreateGUID(element); IFCAnyHandle ownerHistory = exporterIFC.GetOwnerHistoryHandle(); string name = NamingUtil.GetNameOverride(element, NamingUtil.GetIFCName(element)); string description = NamingUtil.GetDescriptionOverride(element, null); string objectType = NamingUtil.GetObjectTypeOverride(element, exporterIFC.GetFamilyName()); IFCAnyHandle zoneHnd = IFCInstanceExporter.CreateZone(file, guid, ownerHistory, name, description, objectType); productWrapper.AddElement(element, zoneHnd); string relAssignsGuid = GUIDUtil.CreateSubElementGUID(element, (int) IFCZoneSubElements.RelAssignsToGroup); IFCInstanceExporter.CreateRelAssignsToGroup(file, relAssignsGuid, ownerHistory, null, null, spaceHnds, null, zoneHnd); tr.Commit(); return; } }
/// <summary> /// Exports an element as a group. /// </summary> /// <param name="exporterIFC">The ExporterIFC object.</param> /// <param name="element">The element.</param> /// <param name="productWrapper">The ProductWrapper.</param> public static void ExportAreaScheme(ExporterIFC exporterIFC, AreaScheme element, ProductWrapper productWrapper) { if (element == null) return; HashSet<IFCAnyHandle> areaHandles = null; if (!ExporterCacheManager.AreaSchemeCache.TryGetValue(element.Id, out areaHandles)) return; if (areaHandles == null || areaHandles.Count == 0) return; IFCFile file = exporterIFC.GetFile(); using (IFCTransaction tr = new IFCTransaction(file)) { string guid = GUIDUtil.CreateGUID(element); IFCAnyHandle ownerHistory = ExporterCacheManager.OwnerHistoryHandle; string name = NamingUtil.GetNameOverride(element, element.Name); string description = NamingUtil.GetDescriptionOverride(element, null); string objectType = NamingUtil.GetObjectTypeOverride(element, exporterIFC.GetFamilyName()); string elementTag = NamingUtil.CreateIFCElementId(element); IFCAnyHandle areaScheme = IFCInstanceExporter.CreateGroup(file, guid, ownerHistory, name, description, objectType); productWrapper.AddElement(element, areaScheme); IFCInstanceExporter.CreateRelAssignsToGroup(file, GUIDUtil.CreateGUID(), ownerHistory, null, null, areaHandles, null, areaScheme); tr.Commit(); return; } }
/// <summary> /// Exports a Group as an IfcGroup. /// </summary> /// <param name="exporterIFC">The ExporterIFC object.</param> /// <param name="element">The element.</param> /// <param name="productWrapper">The ProductWrapper.</param> /// <returns>True if exported successfully, false otherwise.</returns> public static bool ExportGroupElement(ExporterIFC exporterIFC, Group element, ProductWrapper productWrapper) { if (element == null) return false; IFCFile file = exporterIFC.GetFile(); using (IFCTransaction tr = new IFCTransaction(file)) { IFCAnyHandle groupHnd = null; string guid = GUIDUtil.CreateGUID(element); IFCAnyHandle ownerHistory = exporterIFC.GetOwnerHistoryHandle(); string name = NamingUtil.GetNameOverride(element, NamingUtil.GetIFCName(element)); string description = NamingUtil.GetDescriptionOverride(element, null); string objectType = NamingUtil.GetObjectTypeOverride(element, exporterIFC.GetFamilyName()); string ifcEnumType; IFCExportType exportAs = ExporterUtil.GetExportType(exporterIFC, element, out ifcEnumType); if (exportAs == IFCExportType.IfcGroup) { groupHnd = IFCInstanceExporter.CreateGroup(file, guid, ownerHistory, name, description, objectType); } if (groupHnd == null) return false; productWrapper.AddElement(element, groupHnd); ExporterCacheManager.GroupCache.RegisterGroup(element.Id, groupHnd); tr.Commit(); return true; } }
/// <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 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); string openingObjectType = "Opening"; int openingNumber = 1; for (int curr = info.Count - 1; curr >= 0; curr--) { IFCAnyHandle extrusionHandle = ExtrusionExporter.CreateExtrudedSolidFromExtrusionData(exporterIFC, element, info[curr], out _); if (IFCAnyHandleUtil.IsNullOrHasNoValue(extrusionHandle)) { continue; } // Openings shouldn't have surface styles for their geometry. HashSet <IFCAnyHandle> bodyItems = new HashSet <IFCAnyHandle>() { extrusionHandle }; IFCAnyHandle representationHnd = RepresentationUtil.CreateSweptSolidRep(exporterIFC, element, categoryId, exporterIFC.Get3DContextHandle("Body"), bodyItems, null); IList <IFCAnyHandle> representations = IFCAnyHandleUtil.IsNullOrHasNoValue(representationHnd) ? null : new List <IFCAnyHandle>() { representationHnd }; IFCAnyHandle openingRep = IFCInstanceExporter.CreateProductDefinitionShape(file, null, null, representations); IFCAnyHandle openingPlacement = ExporterUtil.CopyLocalPlacement(file, originalPlacement); string guid = GUIDUtil.GenerateIFCGuidFrom(IFCEntityType.IfcOpeningElement, openingNumber.ToString(), elementHandle); IFCAnyHandle ownerHistory = ExporterCacheManager.OwnerHistoryHandle; string openingName = NamingUtil.GetIFCNamePlusIndex(element, openingNumber++); string openingDescription = NamingUtil.GetDescriptionOverride(element, null); string openingTag = NamingUtil.GetTagOverride(element); IFCAnyHandle openingElement = IFCInstanceExporter.CreateOpeningElement(exporterIFC, guid, ownerHistory, openingName, openingDescription, openingObjectType, openingPlacement, openingRep, openingTag); IFCExportInfoPair exportInfo = new IFCExportInfoPair(IFCEntityType.IfcOpeningElement); wrapper.AddElement(null, openingElement, setter, extraParams, true, exportInfo); if (ExporterCacheManager.ExportOptionsCache.ExportBaseQuantities && (extraParams != null)) { PropertyUtil.CreateOpeningQuantities(exporterIFC, openingElement, extraParams); } string voidGuid = GUIDUtil.GenerateIFCGuidFrom(IFCEntityType.IfcRelVoidsElement, elementHandle, openingElement); IFCInstanceExporter.CreateRelVoidsElement(file, voidGuid, ownerHistory, null, null, elementHandle, openingElement); } } }
/// <summary> /// Export IFC common property set, Quantity (if set) and Classification (or Uniformat for COBIE) information for an element. /// </summary> /// <param name="exporterIFC">The exporterIFC class.</param> /// <param name="element">The element.</param> /// <param name="productWrapper">The ProductWrapper class that contains the associated IFC handles.</param> public static void ExportRelatedProperties(ExporterIFC exporterIFC, Element element, ProductWrapper productWrapper) { ExportElementProperties(exporterIFC, element, productWrapper); if (ExporterCacheManager.ExportOptionsCache.ExportBaseQuantities && !(ExporterCacheManager.ExportOptionsCache.FileVersion == IFCVersion.IFCCOBIE)) ExportElementQuantities(exporterIFC, element, productWrapper); ExportElementClassifications(exporterIFC, element, productWrapper); // Exporting ClassificationCode from IFC parameter ExportElementUniformatClassifications(exporterIFC, element, productWrapper); // Default classification, if filled out. }
/// <summary> /// Exports the IFC element quantities. /// </summary> /// <param name="exporterIFC">The IFC exporter object.</param> /// <param name="element ">The element whose quantities are exported.</param> /// <param name="productWrapper">The ProductWrapper object.</param> private static void ExportElementQuantities(ExporterIFC exporterIFC, Element element, ProductWrapper productWrapper) { if (productWrapper.IsEmpty()) return; IFCFile file = exporterIFC.GetFile(); using (IFCTransaction transaction = new IFCTransaction(file)) { Document doc = element.Document; ElementType elemType = doc.GetElement(element.GetTypeId()) as ElementType; IFCAnyHandle ownerHistory = exporterIFC.GetOwnerHistoryHandle(); ICollection<IFCAnyHandle> productSet = productWrapper.GetAllObjects(); IList<IList<QuantityDescription>> quantitiesToCreate = ExporterCacheManager.ParameterCache.Quantities; foreach (IList<QuantityDescription> currStandard in quantitiesToCreate) { foreach (QuantityDescription currDesc in currStandard) { foreach (IFCAnyHandle prodHnd in productSet) { if (currDesc.IsAppropriateType(prodHnd)) { IFCExtrusionCreationData ifcParams = productWrapper.FindExtrusionCreationParameters(prodHnd); HashSet<IFCAnyHandle> quantities = currDesc.ProcessEntries(file, exporterIFC, ifcParams, element, elemType); if (quantities.Count > 0) { string paramSetName = currDesc.Name; string methodName = currDesc.MethodOfMeasurement; IFCAnyHandle propertySet = IFCInstanceExporter.CreateElementQuantity(file, GUIDUtil.CreateGUID(), ownerHistory, paramSetName, methodName, null, quantities); IFCAnyHandle prodHndToUse = prodHnd; DescriptionCalculator ifcRDC = currDesc.DescriptionCalculator; if (ifcRDC != null) { IFCAnyHandle overrideHnd = ifcRDC.RedirectDescription(exporterIFC, element); if (!IFCAnyHandleUtil.IsNullOrHasNoValue(overrideHnd)) prodHndToUse = overrideHnd; } HashSet<IFCAnyHandle> relatedObjects = new HashSet<IFCAnyHandle>(); relatedObjects.Add(prodHndToUse); IFCInstanceExporter.CreateRelDefinesByProperties(file, GUIDUtil.CreateGUID(), ownerHistory, null, null, relatedObjects, propertySet); } } } } } transaction.Commit(); } }
/// <summary> /// Exports Pset_Draughting for IFC 2x2 standard. /// </summary> /// <param name="exporterIFC">The IFC exporter object.</param> /// <param name="element ">The element whose properties are exported.</param> /// <param name="productWrapper">The ProductWrapper object.</param> private static void ExportPsetDraughtingFor2x2(ExporterIFC exporterIFC, Element element, ProductWrapper productWrapper) { IFCFile file = exporterIFC.GetFile(); using (IFCTransaction transaction = new IFCTransaction(file)) { IFCAnyHandle ownerHistory = exporterIFC.GetOwnerHistoryHandle(); string catName = CategoryUtil.GetCategoryName(element); Color color = CategoryUtil.GetElementColor(element); HashSet<IFCAnyHandle> nameAndColorProps = new HashSet<IFCAnyHandle>(); nameAndColorProps.Add(PropertyUtil.CreateLabelPropertyFromCache(file, null, "Layername", catName, PropertyValueType.SingleValue, true, null)); //color { HashSet<IFCAnyHandle> colorProps = new HashSet<IFCAnyHandle>(); colorProps.Add(PropertyUtil.CreateIntegerPropertyFromCache(file, "Red", color.Red, PropertyValueType.SingleValue)); colorProps.Add(PropertyUtil.CreateIntegerPropertyFromCache(file, "Green", color.Green, PropertyValueType.SingleValue)); colorProps.Add(PropertyUtil.CreateIntegerPropertyFromCache(file, "Blue", color.Blue, PropertyValueType.SingleValue)); string propertyName = "Color"; nameAndColorProps.Add(IFCInstanceExporter.CreateComplexProperty(file, propertyName, null, propertyName, colorProps)); } string name = "Pset_Draughting"; // IFC 2x2 standard IFCAnyHandle propertySet2 = IFCInstanceExporter.CreatePropertySet(file, GUIDUtil.CreateGUID(), ownerHistory, name, null, nameAndColorProps); HashSet<IFCAnyHandle> relatedObjects = new HashSet<IFCAnyHandle>(productWrapper.GetAllObjects()); IFCInstanceExporter.CreateRelDefinesByProperties(file, GUIDUtil.CreateGUID(), ownerHistory, null, null, relatedObjects, propertySet2); transaction.Commit(); } }
/// <summary> /// Exports an element as building element proxy. /// </summary> /// <param name="exporterIFC">The ExporterIFC object.</param> /// <param name="element">The element.</param> /// <param name="geometryElement">The geometry element.</param> /// <param name="productWrapper">The ProductWrapper.</param> /// <returns>True if exported successfully, false otherwise.</returns> public static bool Export(ExporterIFC exporterIFC, Element element, GeometryElement geometryElement, ProductWrapper productWrapper) { bool exported = false; if (element == null || geometryElement == null) return exported; IFCFile file = exporterIFC.GetFile(); using (IFCTransaction tr = new IFCTransaction(file)) { exported = (ExportBuildingElementProxy(exporterIFC, element, geometryElement, productWrapper) != null); if (exported) tr.Commit(); } return exported; }
/// <summary> /// Exports materials for host object. /// </summary> /// <param name="exporterIFC">The ExporterIFC object.</param> /// <param name="hostObject">The host object.</param> /// <param name="elemHnd">The host IFC handle.</param> /// <param name="geometryElement">The geometry element.</param> /// <param name="productWrapper">The ProductWrapper.</param> /// <param name="levelId">The level id.</param> /// <param name="direction">The IFCLayerSetDirection.</param> /// <param name="containsBRepGeometry">True if the geometry contains BRep geoemtry. If so, we will export an IfcMaterialList. If null, we will calculate.</param> /// <returns>True if exported successfully, false otherwise.</returns> public static bool ExportHostObjectMaterials(ExporterIFC exporterIFC, HostObject hostObject, IFCAnyHandle elemHnd, GeometryElement geometryElement, ProductWrapper productWrapper, ElementId levelId, Toolkit.IFCLayerSetDirection direction, bool? containsBRepGeometry) { IList<IFCAnyHandle> elemHnds = new List<IFCAnyHandle>(); elemHnds.Add(elemHnd); // Setting doesContainBRepGeometry to false below preserves the original behavior that we created IfcMaterialLists for all geometries. // TODO: calculate, or pass in, a valid bool value for Ceilings, Roofs, and Wall Sweeps. bool doesContainBRepGeometry = containsBRepGeometry.HasValue ? containsBRepGeometry.Value : false; return ExportHostObjectMaterials(exporterIFC, hostObject, elemHnds, geometryElement, productWrapper, levelId, direction, doesContainBRepGeometry); }
/// <summary> /// Exports an element as an IFC assembly with its members. /// </summary> /// <param name="exporterIFC">The exporter.</param> /// <param name="assemblyElem">The element to be exported as IFC assembly.</param> /// <param name="memberIds">The member element ids.</param> /// <param name="assemblyType">The IFC assembly type.</param> /// <param name="productWrapper">The ProductWrapper.</param> static void ExportAssemblyInstanceWithMembers(ExporterIFC exporterIFC, Element assemblyElem, ICollection<ElementId> memberIds, IFCElementAssemblyType assemblyType, ProductWrapper productWrapper) { HashSet<IFCAnyHandle> memberHnds = new HashSet<IFCAnyHandle>(); foreach (ElementId memberId in memberIds) { IFCAnyHandle memberHnd = ExporterCacheManager.ElementToHandleCache.Find(memberId); if (!IFCAnyHandleUtil.IsNullOrHasNoValue(memberHnd)) memberHnds.Add(memberHnd); } if (memberHnds.Count == 0) return; IFCFile file = exporterIFC.GetFile(); using (IFCTransaction tr = new IFCTransaction(file)) { using (PlacementSetter placementSetter = PlacementSetter.Create(exporterIFC, assemblyElem)) { IFCAnyHandle ownerHistory = exporterIFC.GetOwnerHistoryHandle(); IFCAnyHandle localPlacement = placementSetter.LocalPlacement; string guid = GUIDUtil.CreateGUID(assemblyElem); string name = NamingUtil.GetIFCName(assemblyElem); string description = NamingUtil.GetDescriptionOverride(assemblyElem, null); string objectType = NamingUtil.GetObjectTypeOverride(assemblyElem, exporterIFC.GetFamilyName()); string elementTag = NamingUtil.CreateIFCElementId(assemblyElem); IFCAnyHandle assemblyInstanceHnd = IFCInstanceExporter.CreateElementAssembly(file, guid, ownerHistory, name, description, objectType, localPlacement, null, elementTag, IFCAssemblyPlace.NotDefined, assemblyType); productWrapper.AddElement(assemblyElem, assemblyInstanceHnd, placementSetter.LevelInfo, null, true); string aggregateGuid = GUIDUtil.CreateSubElementGUID(assemblyElem, (int)IFCAssemblyInstanceSubElements.RelAggregates); IFCInstanceExporter.CreateRelAggregates(file, aggregateGuid, ownerHistory, null, null, assemblyInstanceHnd, memberHnds); ExporterCacheManager.ElementsInAssembliesCache.UnionWith(memberHnds); // Update member local placements to be relative to the assembly. SetLocalPlacementsRelativeToAssembly(exporterIFC, localPlacement, memberHnds); } tr.Commit(); } }
/// <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; } FamilyInstance openingFInst = openingElem as FamilyInstance; if (openingFInst != null && openingFInst.Host != null) { if (openingFInst.Host.Id != element.Id) { 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); if (isDoorOrWindowOpening) { 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 = !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 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> /// 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> /// 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 a beam to IFC beam. /// </summary> /// <param name="exporterIFC"> /// The ExporterIFC object. /// </param> /// <param name="element"> /// The element to be exported. /// </param> /// <param name="geometryElement"> /// The geometry element. /// </param> /// <param name="productWrapper"> /// The ProductWrapper. /// </param> public static void ExportBeam(ExporterIFC exporterIFC, Element element, GeometryElement geometryElement, ProductWrapper productWrapper) { if (geometryElement == null) return; IFCFile file = exporterIFC.GetFile(); using (IFCTransaction transaction = new IFCTransaction(file)) { LocationCurve locCurve = element.Location as LocationCurve; Transform orientTrf = Transform.Identity; bool canExportAxis = (locCurve != null); IFCAnyHandle axisRep = null; XYZ beamDirection = null; XYZ projDir = null; Curve curve = null; Plane plane = null; if (canExportAxis) { curve = locCurve.Curve; if (curve is Line) { Line line = curve as Line; XYZ planeY, planeOrig; planeOrig = line.GetEndPoint(0); beamDirection = line.Direction; if (Math.Abs(beamDirection.Z) < 0.707) // approx 1.0/sqrt(2.0) { planeY = XYZ.BasisZ.CrossProduct(beamDirection); } else { planeY = XYZ.BasisX.CrossProduct(beamDirection); } planeY = planeY.Normalize(); projDir = beamDirection.CrossProduct(planeY); plane = new Plane(beamDirection, planeY, planeOrig); orientTrf.BasisX = beamDirection; orientTrf.BasisY = planeY; orientTrf.BasisZ = projDir; orientTrf.Origin = planeOrig; } else if (curve is Arc) { XYZ yDir, center; Arc arc = curve as Arc; beamDirection = arc.XDirection; yDir = arc.YDirection; projDir = arc.Normal; center = arc.Center; plane = new Plane(beamDirection, yDir, center); orientTrf.BasisX = beamDirection; orientTrf.BasisY = yDir; orientTrf.BasisZ = projDir; orientTrf.Origin = center; } else canExportAxis = false; } using (PlacementSetter setter = PlacementSetter.Create(exporterIFC, element, null, canExportAxis ? orientTrf : null)) { IFCAnyHandle localPlacement = setter.LocalPlacement; SolidMeshGeometryInfo solidMeshInfo = GeometryUtil.GetSplitSolidMeshGeometry(geometryElement); using (IFCExtrusionCreationData extrusionCreationData = new IFCExtrusionCreationData()) { extrusionCreationData.SetLocalPlacement(localPlacement); if (canExportAxis && (orientTrf.BasisX != null)) { extrusionCreationData.CustomAxis = beamDirection; extrusionCreationData.PossibleExtrusionAxes = IFCExtrusionAxes.TryCustom; } else extrusionCreationData.PossibleExtrusionAxes = IFCExtrusionAxes.TryXY; IList<Solid> solids = solidMeshInfo.GetSolids(); IList<Mesh> meshes = solidMeshInfo.GetMeshes(); ElementId catId = CategoryUtil.GetSafeCategoryId(element); // The representation handle generated from one of the methods below. IFCAnyHandle repHnd = null; // The list of materials in the solids or meshes. ICollection<ElementId> materialIds = new HashSet<ElementId>(); // There may be an offset to make the local coordinate system // be near the origin. This offset will be used to move the axis to the new LCS. Transform offsetTransform = null; // If we have a beam with a Linear location line that only has one solid geometry, // we will try to use the ExtrusionAnalyzer to generate an extrusion with 0 or more clippings. // This code is currently limited in that it will not process beams with openings, so we // use other methods below if this one fails. if (solids.Count == 1 && meshes.Count == 0 && (canExportAxis && (curve is Line))) { bool completelyClipped; beamDirection = orientTrf.BasisX; Plane beamExtrusionPlane = new Plane(orientTrf.BasisY, orientTrf.BasisZ, orientTrf.Origin); repHnd = ExtrusionExporter.CreateExtrusionWithClipping(exporterIFC, element, catId, solids[0], beamExtrusionPlane, beamDirection, null, out completelyClipped); if (completelyClipped) return; if (!IFCAnyHandleUtil.IsNullOrHasNoValue(repHnd)) { // This is used by the BeamSlopeCalculator. This should probably be generated automatically by // CreateExtrusionWithClipping. IFCExtrusionBasis bestAxis = (Math.Abs(beamDirection[0]) > Math.Abs(beamDirection[1])) ? IFCExtrusionBasis.BasisX : IFCExtrusionBasis.BasisY; extrusionCreationData.Slope = GeometryUtil.GetSimpleExtrusionSlope(beamDirection, bestAxis); ElementId materialId = BodyExporter.GetBestMaterialIdFromGeometryOrParameter(solids[0], exporterIFC, element); if (materialId != ElementId.InvalidElementId) materialIds.Add(materialId); } } if (IFCAnyHandleUtil.IsNullOrHasNoValue(repHnd)) { BodyData bodyData = null; BodyExporterOptions bodyExporterOptions = new BodyExporterOptions(true); if (solids.Count > 0 || meshes.Count > 0) { bodyData = BodyExporter.ExportBody(exporterIFC, element, catId, ElementId.InvalidElementId, solids, meshes, bodyExporterOptions, extrusionCreationData); } else { IList<GeometryObject> geomlist = new List<GeometryObject>(); geomlist.Add(geometryElement); bodyData = BodyExporter.ExportBody(exporterIFC, element, catId, ElementId.InvalidElementId, geomlist, bodyExporterOptions, extrusionCreationData); } repHnd = bodyData.RepresentationHnd; materialIds = bodyData.MaterialIds; offsetTransform = bodyData.OffsetTransform; } if (IFCAnyHandleUtil.IsNullOrHasNoValue(repHnd)) { extrusionCreationData.ClearOpenings(); return; } IList<IFCAnyHandle> representations = new List<IFCAnyHandle>(); if (canExportAxis) { XYZ curveOffset = new XYZ(0, 0, 0); if (offsetTransform != null) curveOffset = -UnitUtil.UnscaleLength(offsetTransform.Origin); else { // Note that we do not have to have any scaling adjustment here, since the curve origin is in the // same internal coordinate system as the curve. curveOffset = -plane.Origin; } Plane offsetPlane = new Plane(plane.XVec, plane.YVec, XYZ.Zero); IFCGeometryInfo info = IFCGeometryInfo.CreateCurveGeometryInfo(exporterIFC, offsetPlane, projDir, false); ExporterIFCUtils.CollectGeometryInfo(exporterIFC, info, curve, curveOffset, true); IList<IFCAnyHandle> axis_items = info.GetCurves(); if (axis_items.Count > 0) { string identifierOpt = "Axis"; // this is by IFC2x2 convention, not temporary string representationTypeOpt = "Curve2D"; // this is by IFC2x2 convention, not temporary axisRep = RepresentationUtil.CreateShapeRepresentation(exporterIFC, element, catId, exporterIFC.Get3DContextHandle(identifierOpt), identifierOpt, representationTypeOpt, axis_items); representations.Add(axisRep); } } representations.Add(repHnd); Transform boundingBoxTrf = (offsetTransform == null) ? Transform.Identity : offsetTransform.Inverse; IFCAnyHandle boundingBoxRep = BoundingBoxExporter.ExportBoundingBox(exporterIFC, geometryElement, boundingBoxTrf); if (boundingBoxRep != null) representations.Add(boundingBoxRep); IFCAnyHandle prodRep = IFCInstanceExporter.CreateProductDefinitionShape(file, null, null, representations); string instanceGUID = GUIDUtil.CreateGUID(element); string instanceName = NamingUtil.GetNameOverride(element, NamingUtil.GetIFCName(element)); string instanceDescription = NamingUtil.GetDescriptionOverride(element, null); string instanceObjectType = NamingUtil.GetObjectTypeOverride(element, NamingUtil.CreateIFCObjectName(exporterIFC, element)); string instanceTag = NamingUtil.GetTagOverride(element, NamingUtil.CreateIFCElementId(element)); string preDefinedType = "BEAM"; // Default predefined type for Beam preDefinedType = IFCValidateEntry.GetValidIFCType (element, preDefinedType); IFCAnyHandle beam = IFCInstanceExporter.CreateBeam(file, instanceGUID, exporterIFC.GetOwnerHistoryHandle(), instanceName, instanceDescription, instanceObjectType, extrusionCreationData.GetLocalPlacement(), prodRep, instanceTag, preDefinedType); productWrapper.AddElement(element, beam, setter, extrusionCreationData, true); OpeningUtil.CreateOpeningsIfNecessary(beam, element, extrusionCreationData, offsetTransform, exporterIFC, extrusionCreationData.GetLocalPlacement(), setter, productWrapper); FamilyTypeInfo typeInfo = new FamilyTypeInfo(); typeInfo.ScaledDepth = extrusionCreationData.ScaledLength; typeInfo.ScaledArea = extrusionCreationData.ScaledArea; typeInfo.ScaledInnerPerimeter = extrusionCreationData.ScaledInnerPerimeter; typeInfo.ScaledOuterPerimeter = extrusionCreationData.ScaledOuterPerimeter; PropertyUtil.CreateBeamColumnBaseQuantities(exporterIFC, beam, element, typeInfo, null); if (materialIds.Count != 0) { CategoryUtil.CreateMaterialAssociations(exporterIFC, beam, materialIds); } // Register the beam's IFC handle for later use by truss and beam system export. ExporterCacheManager.ElementToHandleCache.Register(element.Id, beam); } } transaction.Commit(); } }
/// <summary> /// Implements the export of element. /// </summary> /// <param name="exporterIFC">The IFC exporter object.</param> /// <param name="element">The element to export.</param> /// <param name="productWrapper">The ProductWrapper object.</param> public virtual void ExportElementImpl(ExporterIFC exporterIFC, Element element, ProductWrapper productWrapper) { Options options; View ownerView = element.Document.GetElement(element.OwnerViewId) as View; if (ownerView == null) { options = GeometryUtil.GetIFCExportGeometryOptions(); } else { options = new Options(); options.View = ownerView; } GeometryElement geomElem = element.get_Geometry(options); // Default: we don't preserve the element parameter cache after export. bool shouldPreserveParameterCache = false; try { exporterIFC.PushExportState(element, geomElem); Autodesk.Revit.DB.Document doc = element.Document; using (SubTransaction st = new SubTransaction(doc)) { st.Start(); // A long list of supported elements. Please keep in alphabetical order. if (element is AreaReinforcement || element is PathReinforcement || element is Rebar) { RebarExporter.Export(exporterIFC, element, productWrapper); } else if (element is AreaScheme) { AreaSchemeExporter.ExportAreaScheme(exporterIFC, element as AreaScheme, productWrapper); } else if (element is AssemblyInstance) { AssemblyInstance assemblyInstance = element as AssemblyInstance; AssemblyInstanceExporter.ExportAssemblyInstanceElement(exporterIFC, assemblyInstance, productWrapper); } else if (element is BeamSystem) { if (ExporterCacheManager.BeamSystemCache.Contains(element.Id)) AssemblyInstanceExporter.ExportBeamSystem(exporterIFC, element as BeamSystem, productWrapper); else { ExporterCacheManager.BeamSystemCache.Add(element.Id); shouldPreserveParameterCache = true; } } else if (element is Ceiling) { Ceiling ceiling = element as Ceiling; CeilingExporter.ExportCeilingElement(exporterIFC, ceiling, geomElem, productWrapper); } else if (element is CeilingAndFloor || element is Floor) { // This covers both Floors and Building Pads. CeilingAndFloor hostObject = element as CeilingAndFloor; FloorExporter.ExportCeilingAndFloorElement(exporterIFC, hostObject, geomElem, productWrapper); } else if (element is ContFooting) { ContFooting footing = element as ContFooting; FootingExporter.ExportFootingElement(exporterIFC, footing, geomElem, productWrapper); } else if (element is CurveElement) { CurveElement curveElem = element as CurveElement; CurveElementExporter.ExportCurveElement(exporterIFC, curveElem, geomElem, productWrapper); } else if (element is CurtainSystem) { CurtainSystem curtainSystem = element as CurtainSystem; CurtainSystemExporter.ExportCurtainSystem(exporterIFC, curtainSystem, productWrapper); } else if (CurtainSystemExporter.IsLegacyCurtainElement(element)) { CurtainSystemExporter.ExportLegacyCurtainElement(exporterIFC, element, productWrapper); } else if (element is DuctInsulation) { DuctInsulation ductInsulation = element as DuctInsulation; DuctInsulationExporter.ExportDuctInsulation(exporterIFC, ductInsulation, geomElem, productWrapper); } else if (element is DuctLining) { DuctLining ductLining = element as DuctLining; DuctLiningExporter.ExportDuctLining(exporterIFC, ductLining, geomElem, productWrapper); } else if (element is ElectricalSystem) { ExporterCacheManager.SystemsCache.AddElectricalSystem(element.Id); } else if (element is FabricArea) { // We are exporting the fabric area as a group only. FabricSheetExporter.ExportFabricArea(exporterIFC, element, productWrapper); } else if (element is FabricSheet) { FabricSheet fabricSheet = element as FabricSheet; FabricSheetExporter.ExportFabricSheet(exporterIFC, fabricSheet, geomElem, productWrapper); } else if (element is FaceWall) { WallExporter.ExportWall(exporterIFC, element, null, geomElem, productWrapper); } else if (element is FamilyInstance) { FamilyInstance familyInstanceElem = element as FamilyInstance; FamilyInstanceExporter.ExportFamilyInstanceElement(exporterIFC, familyInstanceElem, geomElem, productWrapper); } else if (element is FilledRegion) { FilledRegion filledRegion = element as FilledRegion; FilledRegionExporter.Export(exporterIFC, filledRegion, geomElem, productWrapper); } else if (element is Grid) { ExporterCacheManager.GridCache.Add(element); } else if (element is Group) { Group group = element as Group; GroupExporter.ExportGroupElement(exporterIFC, group, productWrapper); } else if (element is HostedSweep) { HostedSweep hostedSweep = element as HostedSweep; HostedSweepExporter.Export(exporterIFC, hostedSweep, geomElem, productWrapper); } else if (element is Part) { Part part = element as Part; if (ExporterCacheManager.ExportOptionsCache.ExportPartsAsBuildingElements) PartExporter.ExportPartAsBuildingElement(exporterIFC, part, geomElem, productWrapper); else PartExporter.ExportStandalonePart(exporterIFC, part, geomElem, productWrapper); } else if (element is PipeInsulation) { PipeInsulation pipeInsulation = element as PipeInsulation; PipeInsulationExporter.ExportPipeInsulation(exporterIFC, pipeInsulation, geomElem, productWrapper); } else if (element is Railing) { if (ExporterCacheManager.RailingCache.Contains(element.Id)) RailingExporter.ExportRailingElement(exporterIFC, element as Railing, productWrapper); else { ExporterCacheManager.RailingCache.Add(element.Id); RailingExporter.AddSubElementsToCache(element as Railing); shouldPreserveParameterCache = true; } } else if (RampExporter.IsRamp(element)) { RampExporter.Export(exporterIFC, element, geomElem, productWrapper); } else if (element is RoofBase) { RoofBase roofElement = element as RoofBase; RoofExporter.Export(exporterIFC, roofElement, geomElem, productWrapper); } else if (element is SpatialElement) { SpatialElement spatialElem = element as SpatialElement; SpatialElementExporter.ExportSpatialElement(exporterIFC, spatialElem, productWrapper); } else if (IsStairs(element)) { StairsExporter.Export(exporterIFC, element, geomElem, productWrapper); } else if (element is TextNote) { TextNote textNote = element as TextNote; TextNoteExporter.Export(exporterIFC, textNote, productWrapper); } else if (element is TopographySurface) { TopographySurface topSurface = element as TopographySurface; SiteExporter.ExportTopographySurface(exporterIFC, topSurface, geomElem, productWrapper); } else if (element is Truss) { if (ExporterCacheManager.TrussCache.Contains(element.Id)) AssemblyInstanceExporter.ExportTrussElement(exporterIFC, element as Truss, productWrapper); else { ExporterCacheManager.TrussCache.Add(element.Id); shouldPreserveParameterCache = true; } } else if (element is Wall) { Wall wallElem = element as Wall; WallExporter.Export(exporterIFC, wallElem, geomElem, productWrapper); } else if (element is WallSweep) { WallSweep wallSweep = element as WallSweep; WallSweepExporter.Export(exporterIFC, wallSweep, geomElem, productWrapper); } else if (element is Zone) { if (ExporterCacheManager.ZoneCache.Contains(element.Id)) ZoneExporter.ExportZone(exporterIFC, element as Zone, productWrapper); else { ExporterCacheManager.ZoneCache.Add(element.Id); shouldPreserveParameterCache = true; } } else { string ifcEnumType; IFCExportType exportType = ExporterUtil.GetExportType(exporterIFC, element, out ifcEnumType); bool exported = false; if (IsMEPType(exporterIFC, element, exportType)) exported = GenericMEPExporter.Export(exporterIFC, element, geomElem, exportType, ifcEnumType, productWrapper); else if (ExportAsProxy(element, exportType)) exported = ProxyElementExporter.Export(exporterIFC, element, geomElem, productWrapper); // For ducts and pipes, we will add a IfcRelCoversBldgElements during the end of export. if (exported && (element is Duct || element is Pipe)) ExporterCacheManager.MEPCache.CoveredElementsCache.Add(element.Id); } if (element.AssemblyInstanceId != ElementId.InvalidElementId) ExporterCacheManager.AssemblyInstanceCache.RegisterElements(element.AssemblyInstanceId, productWrapper); if (element.GroupId != ElementId.InvalidElementId) ExporterCacheManager.GroupCache.RegisterElements(element.GroupId, productWrapper); st.RollBack(); } } finally { exporterIFC.PopExportState(); ExporterStateManager.PreserveElementParameterCache(element, shouldPreserveParameterCache); } }
/// <summary> /// Exports an element as an IFC assembly. /// </summary> /// <param name="exporterIFC">The ExporterIFC object.</param> /// <param name="element">The element.</param> /// <param name="productWrapper">The ProductWrapper.</param> /// <returns>True if exported successfully, false otherwise.</returns> public static bool ExportAssemblyInstanceElement(ExporterIFC exporterIFC, AssemblyInstance element, ProductWrapper productWrapper) { if (element == null) return false; IFCFile file = exporterIFC.GetFile(); using (IFCTransaction tr = new IFCTransaction(file)) { IFCAnyHandle assemblyInstanceHnd = null; string guid = GUIDUtil.CreateGUID(element); IFCAnyHandle ownerHistory = exporterIFC.GetOwnerHistoryHandle(); string name = NamingUtil.GetNameOverride(element, NamingUtil.GetIFCName(element)); string description = NamingUtil.GetDescriptionOverride(element, null); string objectType = NamingUtil.GetObjectTypeOverride(element, exporterIFC.GetFamilyName()); IFCAnyHandle localPlacement = null; PlacementSetter placementSetter = null; IFCLevelInfo levelInfo = null; string ifcEnumType; IFCExportType exportAs = ExporterUtil.GetExportType(exporterIFC, element, out ifcEnumType); if (exportAs == IFCExportType.IfcSystem) { assemblyInstanceHnd = IFCInstanceExporter.CreateSystem(file, guid, ownerHistory, name, description, objectType); // Create classification reference when System has classification filed name assigned to it ClassificationUtil.CreateClassification(exporterIFC, file, element, assemblyInstanceHnd); HashSet<IFCAnyHandle> relatedBuildings = new HashSet<IFCAnyHandle>(); relatedBuildings.Add(ExporterCacheManager.BuildingHandle); IFCAnyHandle relServicesBuildings = IFCInstanceExporter.CreateRelServicesBuildings(file, GUIDUtil.CreateGUID(), exporterIFC.GetOwnerHistoryHandle(), null, null, assemblyInstanceHnd, relatedBuildings); } else { using (placementSetter = PlacementSetter.Create(exporterIFC, element)) { string elementTag = NamingUtil.GetTagOverride(element, NamingUtil.CreateIFCElementId(element)); IFCAnyHandle representation = null; // We have limited support for exporting assemblies as other container types. localPlacement = placementSetter.LocalPlacement; levelInfo = placementSetter.LevelInfo; ifcEnumType = IFCValidateEntry.GetValidIFCType(element, ifcEnumType); switch (exportAs) { case IFCExportType.IfcCurtainWall: assemblyInstanceHnd = IFCInstanceExporter.CreateCurtainWall(file, guid, ownerHistory, name, description, objectType, localPlacement, representation, elementTag); break; case IFCExportType.IfcRamp: string rampPredefinedType = RampExporter.GetIFCRampType(ifcEnumType); assemblyInstanceHnd = IFCInstanceExporter.CreateRamp(file, guid, ownerHistory, name, description, objectType, localPlacement, representation, elementTag, rampPredefinedType); break; case IFCExportType.IfcRoof: assemblyInstanceHnd = IFCInstanceExporter.CreateRoof(file, guid, ownerHistory, name, description, objectType, localPlacement, representation, elementTag, ifcEnumType); break; case IFCExportType.IfcStair: string stairPredefinedType = StairsExporter.GetIFCStairType(ifcEnumType); assemblyInstanceHnd = IFCInstanceExporter.CreateStair(file, guid, ownerHistory, name, description, objectType, localPlacement, representation, elementTag, stairPredefinedType); break; case IFCExportType.IfcWall: assemblyInstanceHnd = IFCInstanceExporter.CreateWall(file, guid, ownerHistory, name, description, objectType, localPlacement, representation, elementTag, ifcEnumType); break; default: IFCElementAssemblyType assemblyPredefinedType = GetPredefinedTypeFromObjectType(objectType); assemblyInstanceHnd = IFCInstanceExporter.CreateElementAssembly(file, guid, ownerHistory, name, description, objectType, localPlacement, representation, elementTag, IFCAssemblyPlace.NotDefined, assemblyPredefinedType); break; } } } if (assemblyInstanceHnd == null) return false; bool relateToLevel = (levelInfo != null); productWrapper.AddElement(element, assemblyInstanceHnd, levelInfo, null, relateToLevel); ExporterCacheManager.AssemblyInstanceCache.RegisterAssemblyInstance(element.Id, assemblyInstanceHnd); tr.Commit(); return true; } }
/// <summary> /// Exports materials for host object. /// </summary> /// <param name="exporterIFC">The ExporterIFC object.</param> /// <param name="hostObject">The host object.</param> /// <param name="elemHnds">The host IFC handles.</param> /// <param name="geometryElement">The geometry element.</param> /// <param name="productWrapper">The ProductWrapper.</param> /// <param name="levelId">The level id.</param> /// <param name="direction">The IFCLayerSetDirection.</param> /// <param name="containsBRepGeometry">True if the geometry contains BRep geoemtry. If so, we will export an IfcMaterialList</param> /// <returns>True if exported successfully, false otherwise.</returns> public static bool ExportHostObjectMaterials(ExporterIFC exporterIFC, HostObject hostObject, IList<IFCAnyHandle> elemHnds, GeometryElement geometryElement, ProductWrapper productWrapper, ElementId levelId, Toolkit.IFCLayerSetDirection direction, bool containsBRepGeometry) { if (hostObject == null) return true; //nothing to do if (elemHnds == null || (elemHnds.Count == 0)) return true; //nothing to do IFCFile file = exporterIFC.GetFile(); using (IFCTransaction tr = new IFCTransaction(file)) { if (productWrapper != null) productWrapper.ClearFinishMaterials(); double scaledOffset = 0.0, scaledWallWidth = 0.0, wallHeight = 0.0; Wall wall = hostObject as Wall; if (wall != null) { scaledWallWidth = UnitUtil.ScaleLength(wall.Width); scaledOffset = -scaledWallWidth / 2.0; BoundingBoxXYZ boundingBox = wall.get_BoundingBox(null); if (boundingBox != null) wallHeight = boundingBox.Max.Z - boundingBox.Min.Z; } ElementId typeElemId = hostObject.GetTypeId(); IFCAnyHandle materialLayerSet = ExporterCacheManager.MaterialLayerSetCache.Find(typeElemId); // Roofs with no components are only allowed one material. We will arbitrarily choose the thickest material. IFCAnyHandle primaryMaterialHnd = ExporterCacheManager.MaterialLayerSetCache.FindPrimaryMaterialHnd(typeElemId); if (IFCAnyHandleUtil.IsNullOrHasNoValue(materialLayerSet)) { HostObjAttributes hostObjAttr = hostObject.Document.GetElement(typeElemId) as HostObjAttributes; if (hostObjAttr == null) return true; //nothing to do List<ElementId> matIds = new List<ElementId>(); List<double> widths = new List<double>(); List<MaterialFunctionAssignment> functions = new List<MaterialFunctionAssignment>(); ElementId baseMatId = CategoryUtil.GetBaseMaterialIdForElement(hostObject); CompoundStructure cs = hostObjAttr.GetCompoundStructure(); if (cs != null) { //TODO: Vertically compound structures are not yet supported by export. if (!cs.IsVerticallyHomogeneous() && !MathUtil.IsAlmostZero(wallHeight)) cs = cs.GetSimpleCompoundStructure(wallHeight, wallHeight / 2.0); for (int i = 0; i < cs.LayerCount; ++i) { ElementId matId = cs.GetMaterialId(i); if (matId != ElementId.InvalidElementId) { matIds.Add(matId); } else { matIds.Add(baseMatId); } widths.Add(cs.GetLayerWidth(i)); // save layer function into ProductWrapper, // it's used while exporting "Function" of Pset_CoveringCommon functions.Add(cs.GetLayerFunction(i)); } } if (matIds.Count == 0) { matIds.Add(baseMatId); widths.Add(cs != null ? cs.GetWidth() : 0); functions.Add(MaterialFunctionAssignment.None); } // We can't create IfcMaterialLayers without creating an IfcMaterialLayerSet. So we will simply collate here. IList<IFCAnyHandle> materialHnds = new List<IFCAnyHandle>(); IList<int> widthIndices = new List<int>(); double thickestLayer = 0.0; for (int ii = 0; ii < matIds.Count; ++ii) { // Require positive width for IFC2x3 and before, and non-negative width for IFC4. if (widths[ii] < -MathUtil.Eps()) continue; bool almostZeroWidth = MathUtil.IsAlmostZero(widths[ii]); if (ExporterCacheManager.ExportOptionsCache.FileVersion != IFCVersion.IFC4 && almostZeroWidth) continue; if (almostZeroWidth) widths[ii] = 0.0; IFCAnyHandle materialHnd = CategoryUtil.GetOrCreateMaterialHandle(exporterIFC, matIds[ii]); if (primaryMaterialHnd == null || (widths[ii] > thickestLayer)) { primaryMaterialHnd = materialHnd; thickestLayer = widths[ii]; } widthIndices.Add(ii); materialHnds.Add(materialHnd); if ((productWrapper != null) && (functions[ii] == MaterialFunctionAssignment.Finish1 || functions[ii] == MaterialFunctionAssignment.Finish2)) { productWrapper.AddFinishMaterial(materialHnd); } } int numLayersToCreate = widthIndices.Count; if (numLayersToCreate == 0) return false; if (!containsBRepGeometry) { IList<IFCAnyHandle> layers = new List<IFCAnyHandle>(numLayersToCreate); for (int ii = 0; ii < numLayersToCreate; ii++) { int widthIndex = widthIndices[ii]; double scaledWidth = UnitUtil.ScaleLength(widths[widthIndex]); IFCAnyHandle materialLayer = IFCInstanceExporter.CreateMaterialLayer(file, materialHnds[ii], scaledWidth, null); layers.Add(materialLayer); } string layerSetName = exporterIFC.GetFamilyName(); materialLayerSet = IFCInstanceExporter.CreateMaterialLayerSet(file, layers, layerSetName); ExporterCacheManager.MaterialLayerSetCache.Register(typeElemId, materialLayerSet); ExporterCacheManager.MaterialLayerSetCache.RegisterPrimaryMaterialHnd(typeElemId, primaryMaterialHnd); } else { foreach (IFCAnyHandle elemHnd in elemHnds) { CategoryUtil.CreateMaterialAssociations(exporterIFC, elemHnd, matIds); } } } // IfcMaterialLayerSetUsage is not supported for IfcWall, only IfcWallStandardCase. IFCAnyHandle layerSetUsage = null; for (int ii = 0; ii < elemHnds.Count; ii++) { IFCAnyHandle elemHnd = elemHnds[ii]; if (IFCAnyHandleUtil.IsNullOrHasNoValue(elemHnd)) continue; SpaceBoundingElementUtil.RegisterSpaceBoundingElementHandle(exporterIFC, elemHnd, hostObject.Id, levelId); if (containsBRepGeometry) continue; HashSet<IFCAnyHandle> relDecomposesSet = IFCAnyHandleUtil.GetRelDecomposes(elemHnd); IList<IFCAnyHandle> subElemHnds = null; if (relDecomposesSet != null && relDecomposesSet.Count == 1) { IFCAnyHandle relAggregates = relDecomposesSet.First(); if (IFCAnyHandleUtil.IsTypeOf(relAggregates, IFCEntityType.IfcRelAggregates)) subElemHnds = IFCAnyHandleUtil.GetAggregateInstanceAttribute<List<IFCAnyHandle>>(relAggregates, "RelatedObjects"); } bool hasSubElems = (subElemHnds != null && subElemHnds.Count != 0); bool isRoof = IFCAnyHandleUtil.IsTypeOf(elemHnd, IFCEntityType.IfcRoof); if (!hasSubElems && !isRoof && !IFCAnyHandleUtil.IsTypeOf(elemHnd, IFCEntityType.IfcWall)) { if (layerSetUsage == null) { bool flipDirSense = true; if (wall != null) { // if we have flipped the center curve on export, we need to take that into account here. // We flip the center curve on export if it is an arc and it has a negative Z direction. LocationCurve locCurve = wall.Location as LocationCurve; if (locCurve != null) { Curve curve = locCurve.Curve; Plane defPlane = new Plane(XYZ.BasisX, XYZ.BasisY, XYZ.Zero); bool curveFlipped = GeometryUtil.MustFlipCurve(defPlane, curve); flipDirSense = !(wall.Flipped ^ curveFlipped); } } else if (hostObject is Floor) { flipDirSense = false; } double offsetFromReferenceLine = flipDirSense ? -scaledOffset : scaledOffset; IFCDirectionSense sense = flipDirSense ? IFCDirectionSense.Negative : IFCDirectionSense.Positive; layerSetUsage = IFCInstanceExporter.CreateMaterialLayerSetUsage(file, materialLayerSet, direction, sense, offsetFromReferenceLine); } ExporterCacheManager.MaterialLayerRelationsCache.Add(layerSetUsage, elemHnd); } else { if (hasSubElems) { foreach (IFCAnyHandle subElemHnd in subElemHnds) { if (!IFCAnyHandleUtil.IsNullOrHasNoValue(subElemHnd)) ExporterCacheManager.MaterialLayerRelationsCache.Add(materialLayerSet, subElemHnd); } } else if (!isRoof) { ExporterCacheManager.MaterialLayerRelationsCache.Add(materialLayerSet, elemHnd); } else if (primaryMaterialHnd != null) { ExporterCacheManager.MaterialLayerRelationsCache.Add(primaryMaterialHnd, elemHnd); } } } tr.Commit(); return true; } }
/// <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); } } }
private void GenerateIFCObjectsIfNeeded() { if (m_needToGenerateIFCObjects) { m_needToGenerateIFCObjects = false; } else { return; } IFCAnyHandle materialLayerSet = null; if (m_ProductWrapper != null && !m_ProductWrapper.ToNative().IsValidObject) { m_ProductWrapper = null; } m_ProductWrapper?.ClearFinishMaterials(); // We can't create IfcMaterialLayers without creating an IfcMaterialLayerSet. So we will simply collate here. IList <IFCAnyHandle> materialHnds = new List <IFCAnyHandle>(); IList <int> widthIndices = new List <int>(); double thickestLayer = 0.0; for (int ii = 0; ii < MaterialIds.Count; ++ii) { // Require positive width for IFC2x3 and before, and non-negative width for IFC4. if (MaterialIds[ii].m_matWidth < -MathUtil.Eps()) { continue; } bool almostZeroWidth = MathUtil.IsAlmostZero(MaterialIds[ii].m_matWidth); if (!ExporterCacheManager.ExportOptionsCache.ExportAs4 && almostZeroWidth) { continue; } if (almostZeroWidth) { MaterialIds[ii].m_matWidth = 0.0; } IFCAnyHandle materialHnd = CategoryUtil.GetOrCreateMaterialHandle(m_ExporterIFC, MaterialIds[ii].m_baseMatId); if (m_PrimaryMaterialHandle == null || (MaterialIds[ii].m_matWidth > thickestLayer)) { m_PrimaryMaterialHandle = materialHnd; thickestLayer = MaterialIds[ii].m_matWidth; } widthIndices.Add(ii); materialHnds.Add(materialHnd); if ((m_ProductWrapper != null) && (MaterialIds[ii].m_function == MaterialFunctionAssignment.Finish1 || MaterialIds[ii].m_function == MaterialFunctionAssignment.Finish2)) { m_ProductWrapper.AddFinishMaterial(materialHnd); } } int numLayersToCreate = widthIndices.Count; if (numLayersToCreate == 0) { m_MaterialLayerSetHandle = materialLayerSet; return; } // If it is a single material, check single material override (only IfcMaterial without IfcMaterialLayerSet with only 1 member) if (numLayersToCreate == 1 && ExporterCacheManager.ExportOptionsCache.ExportAs4ReferenceView) { m_MaterialLayerSetHandle = ExporterUtil.GetSingleMaterial(m_ExporterIFC, m_Element, MaterialIds[0].m_baseMatId) ?? materialHnds[0]; return; } IFCFile file = m_ExporterIFC.GetFile(); Document document = ExporterCacheManager.Document; IList <IFCAnyHandle> layers = new List <IFCAnyHandle>(numLayersToCreate); IList <Tuple <string, IFCAnyHandle> > layerWidthQuantities = new List <Tuple <string, IFCAnyHandle> >(); HashSet <string> layerNameUsed = new HashSet <string>(); double totalWidth = 0.0; for (int ii = 0; ii < numLayersToCreate; ii++) { int widthIndex = widthIndices[ii]; double scaledWidth = UnitUtil.ScaleLength(MaterialIds[widthIndex].m_matWidth); string layerName = "Layer"; string description = null; string category = null; int? priority = null; IFCLogical?isVentilated = null; int isVentilatedValue; Material material = document.GetElement(MaterialIds[ii].m_baseMatId) as Material; if (material != null) { if (ParameterUtil.GetIntValueFromElement(material, "IfcMaterialLayer.IsVentilated", out isVentilatedValue) != null) { if (isVentilatedValue == 0) { isVentilated = IFCLogical.False; } else if (isVentilatedValue == 1) { isVentilated = IFCLogical.True; } } if (ExporterCacheManager.ExportOptionsCache.ExportAs4) { layerName = MaterialIds[ii].m_layerName; if (string.IsNullOrEmpty(layerName)) { layerName = "Layer"; } // Ensure layer name is unique layerName = NamingUtil.GetUniqueNameWithinSet(layerName, ref layerNameUsed); description = NamingUtil.GetOverrideStringValue(material, "IfcMaterialLayer.Description", IFCAnyHandleUtil.GetStringAttribute(materialHnds[ii], "Description")); category = NamingUtil.GetOverrideStringValue(material, "IfcMaterialLayer.Category", IFCAnyHandleUtil.GetStringAttribute(materialHnds[ii], "Category")); int priorityValue; if (ParameterUtil.GetIntValueFromElement(material, "IfcMaterialLayer.Priority", out priorityValue) != null) { priority = priorityValue; } } } if (ExporterCacheManager.ExportOptionsCache.ExportAs4ReferenceView) { // Skip component that has zero width (the will be no geometry associated to it if (MathUtil.IsAlmostZero(scaledWidth)) { continue; } IFCAnyHandle materialConstituent = IFCInstanceExporter.CreateMaterialConstituent(file, materialHnds[ii], name: layerName, description: description, category: category); layers.Add(materialConstituent); IFCAnyHandle layerQtyHnd = IFCInstanceExporter.CreateQuantityLength(file, "Width", description, null, scaledWidth); totalWidth += scaledWidth; layerWidthQuantities.Add(new Tuple <string, IFCAnyHandle>(layerName, layerQtyHnd)); } else { IFCAnyHandle materialLayer = IFCInstanceExporter.CreateMaterialLayer(file, materialHnds[ii], scaledWidth, isVentilated, name: layerName, description: description, category: category, priority: priority); layers.Add(materialLayer); } } ElementId typeElemId = m_Element.GetTypeId(); if (layers.Count > 0) { Element type = document.GetElement(typeElemId); string layerSetName = NamingUtil.GetOverrideStringValue(type, "IfcMaterialLayerSet.Name", m_ExporterIFC.GetFamilyName()); string layerSetDesc = NamingUtil.GetOverrideStringValue(type, "IfcMaterialLayerSet.Description", null); if (ExporterCacheManager.ExportOptionsCache.ExportAs4ReferenceView) { HashSet <IFCAnyHandle> constituents = new HashSet <IFCAnyHandle>(layers); m_MaterialLayerSetHandle = IFCInstanceExporter.CreateMaterialConstituentSet(file, constituents, name: layerSetName, description: layerSetDesc); foreach (Tuple <string, IFCAnyHandle> layerWidthQty in layerWidthQuantities) { m_LayerQuantityWidthHnd.Add(IFCInstanceExporter.CreatePhysicalComplexQuantity(file, layerWidthQty.Item1, null, new HashSet <IFCAnyHandle>() { layerWidthQty.Item2 }, "Layer", null, null)); } // Finally create the total width as a quantity m_LayerQuantityWidthHnd.Add(IFCInstanceExporter.CreateQuantityLength(file, "Width", null, null, totalWidth)); } else { m_MaterialLayerSetHandle = IFCInstanceExporter.CreateMaterialLayerSet(file, layers, layerSetName, layerSetDesc); } ExporterCacheManager.MaterialSetCache.RegisterLayerSet(typeElemId, m_MaterialLayerSetHandle, this); } if (!IFCAnyHandleUtil.IsNullOrHasNoValue(m_PrimaryMaterialHandle)) { ExporterCacheManager.MaterialSetCache.RegisterPrimaryMaterialHnd(typeElemId, m_PrimaryMaterialHandle); } }
/// <summary> /// Collect information to create space occupants and cache them to create when end export. /// </summary> /// <param name="exporterIFC"> /// The exporterIFC object. /// </param> /// <param name="file"> /// The IFCFile object. /// </param> /// <param name="element"> /// The element. /// </param> /// <param name="productWrapper"> /// The ProductWrapper. /// </param> static void CreateSpaceOccupantInfo(ExporterIFC exporterIFC, IFCFile file, Element element, ProductWrapper productWrapper) { IFCAnyHandle roomHandle = productWrapper.GetElementOfType(IFCEntityType.IfcSpace); bool exportToCOBIE = ExporterCacheManager.ExportOptionsCache.ExportAsCOBIE; string name; if (ParameterUtil.GetStringValueFromElement(element.Id, "Occupant", out name) != null) { Dictionary<string, IFCAnyHandle> classificationHandles = new Dictionary<string, IFCAnyHandle>(); // Classifications. if (exportToCOBIE) { Document doc = element.Document; ProjectInfo projectInfo = doc.ProjectInformation; string location = null; if (projectInfo != null) ParameterUtil.GetStringValueFromElement(projectInfo.Id, "BIM Standards URL", out location); string itemReference; if (ParameterUtil.GetStringValueFromElementOrSymbol(element, "Space Occupant Organization ID Reference", out itemReference) != null) { string itemName; ParameterUtil.GetStringValueFromElementOrSymbol(element, "Space Occupant Organization ID Name", out itemName); IFCAnyHandle classificationReference = IFCInstanceExporter.CreateClassificationReference(file, location, itemReference, itemName, null); classificationHandles["Space Occupant Organization ID"] = classificationReference; } if (ParameterUtil.GetStringValueFromElementOrSymbol(element, "Space Occupant Sub-Organization ID Reference", out itemReference) != null) { string itemName; ParameterUtil.GetStringValueFromElementOrSymbol(element, "Space Occupant Sub-Organization ID Name", out itemName); IFCAnyHandle classificationReference = IFCInstanceExporter.CreateClassificationReference(file, location, itemReference, itemName, null); classificationHandles["Space Occupant Sub-Organization ID"] = classificationReference; } if (ParameterUtil.GetStringValueFromElementOrSymbol(element, "Space Occupant Sub-Organization ID Reference", out itemReference) != null) { string itemName; ParameterUtil.GetStringValueFromElementOrSymbol(element, "Space Occupant Sub-Organization ID Name", out itemName); IFCAnyHandle classificationReference = IFCInstanceExporter.CreateClassificationReference(file, location, itemReference, itemName, null); classificationHandles["Space Occupant Sub-Organization ID"] = classificationReference; } if (ParameterUtil.GetStringValueFromElementOrSymbol(element, "Space Occupant Organization Billing ID Reference", out itemReference) != null) { string itemName; ParameterUtil.GetStringValueFromElementOrSymbol(element, "Space Occupant Organization Billing ID Name", out itemName); IFCAnyHandle classificationReference = IFCInstanceExporter.CreateClassificationReference(file, location, itemReference, itemName, null); classificationHandles["Space Occupant Organization Billing ID"] = classificationReference; } } // Look for Parameter Set definition. We don't use the general approach as Space Occupants are not "real" elements. IFCAnyHandle spaceOccupantPSetHnd = CreatePSetSpaceOccupant(exporterIFC, file, element); SpaceOccupantInfo spaceOccupantInfo = ExporterCacheManager.SpaceOccupantInfoCache.Find(name); if (spaceOccupantInfo == null) { spaceOccupantInfo = new SpaceOccupantInfo(roomHandle, classificationHandles, spaceOccupantPSetHnd); ExporterCacheManager.SpaceOccupantInfoCache.Register(name, spaceOccupantInfo); } else { spaceOccupantInfo.RoomHandles.Add(roomHandle); foreach (KeyValuePair<string, IFCAnyHandle> classificationReference in classificationHandles) { if (!spaceOccupantInfo.ClassificationReferences[classificationReference.Key].HasValue) spaceOccupantInfo.ClassificationReferences[classificationReference.Key] = classificationReference.Value; else { // Delete redundant IfcClassificationReference from file. classificationReference.Value.Delete(); } } if (spaceOccupantInfo.SpaceOccupantProperySetHandle == null || !spaceOccupantInfo.SpaceOccupantProperySetHandle.HasValue) spaceOccupantInfo.SpaceOccupantProperySetHandle = spaceOccupantPSetHnd; else if (spaceOccupantPSetHnd.HasValue) spaceOccupantPSetHnd.Delete(); } } }
/// <summary> /// Exports the element properties. /// </summary> /// <param name="exporterIFC">The IFC exporter object.</param> /// <param name="element">The element whose properties are exported.</param> /// <param name="productWrapper">The ProductWrapper object.</param> private static void ExportElementProperties(ExporterIFC exporterIFC, Element element, ProductWrapper productWrapper) { if (productWrapper.IsEmpty()) return; IFCFile file = exporterIFC.GetFile(); using (IFCTransaction transaction = new IFCTransaction(file)) { Document doc = element.Document; ElementType elemType = doc.GetElement(element.GetTypeId()) as ElementType; IFCAnyHandle ownerHistory = exporterIFC.GetOwnerHistoryHandle(); ICollection<IFCAnyHandle> productSet = productWrapper.GetAllObjects(); IList<IList<PropertySetDescription>> psetsToCreate = ExporterCacheManager.ParameterCache.PropertySets; // In some cases, like multi-story stairs and ramps, we may have the same Pset used for multiple levels. // If ifcParams is null, re-use the property set. ISet<string> locallyUsedGUIDs = new HashSet<string>(); IDictionary<Tuple<Element, Element, string>, IFCAnyHandle> createdPropertySets = new Dictionary<Tuple<Element, Element, string>, IFCAnyHandle>(); IDictionary<IFCAnyHandle, HashSet<IFCAnyHandle>> relDefinesByPropertiesMap = new Dictionary<IFCAnyHandle, HashSet<IFCAnyHandle>>(); foreach (IFCAnyHandle prodHnd in productSet) { IList<PropertySetDescription> currPsetsToCreate = GetCurrPSetsToCreate(prodHnd, psetsToCreate); if (currPsetsToCreate.Count == 0) continue; ElementId overrideElementId = ExporterCacheManager.HandleToElementCache.Find(prodHnd); Element elementToUse = (overrideElementId == ElementId.InvalidElementId) ? element : doc.GetElement(overrideElementId); ElementType elemTypeToUse = (overrideElementId == ElementId.InvalidElementId) ? elemType : doc.GetElement(elementToUse.GetTypeId()) as ElementType; if (elemTypeToUse == null) elemTypeToUse = elemType; IFCExtrusionCreationData ifcParams = productWrapper.FindExtrusionCreationParameters(prodHnd); foreach (PropertySetDescription currDesc in currPsetsToCreate) { // Last conditional check: if the property set comes from a ViewSchedule, check if the element is in the schedule. if (currDesc.ViewScheduleId != ElementId.InvalidElementId) if (!ExporterCacheManager.ViewScheduleElementCache[currDesc.ViewScheduleId].Contains(elementToUse.Id)) continue; Tuple<Element, Element, string> propertySetKey = new Tuple<Element, Element, string>(elementToUse, elemTypeToUse, currDesc.Name); IFCAnyHandle propertySet = null; if ((ifcParams != null) || (!createdPropertySets.TryGetValue(propertySetKey, out propertySet))) { HashSet<IFCAnyHandle> props = currDesc.ProcessEntries(file, exporterIFC, ifcParams, elementToUse, elemTypeToUse); if (props.Count > 0) { int subElementIndex = CheckElementTypeValidityForSubIndex(currDesc, prodHnd, element); string guid = GUIDUtil.CreateSubElementGUID(elementToUse, subElementIndex); if (locallyUsedGUIDs.Contains(guid)) guid = GUIDUtil.CreateGUID(); else locallyUsedGUIDs.Add(guid); string paramSetName = currDesc.Name; propertySet = IFCInstanceExporter.CreatePropertySet(file, guid, ownerHistory, paramSetName, null, props); if (ifcParams == null) createdPropertySets[propertySetKey] = propertySet; } } if (propertySet != null) { IFCAnyHandle prodHndToUse = prodHnd; DescriptionCalculator ifcRDC = currDesc.DescriptionCalculator; if (ifcRDC != null) { IFCAnyHandle overrideHnd = ifcRDC.RedirectDescription(exporterIFC, elementToUse); if (!IFCAnyHandleUtil.IsNullOrHasNoValue(overrideHnd)) prodHndToUse = overrideHnd; } HashSet<IFCAnyHandle> relatedObjects = null; if (!relDefinesByPropertiesMap.TryGetValue(propertySet, out relatedObjects)) { relatedObjects = new HashSet<IFCAnyHandle>(); relDefinesByPropertiesMap[propertySet] = relatedObjects; } relatedObjects.Add(prodHndToUse); } } } foreach (KeyValuePair<IFCAnyHandle, HashSet<IFCAnyHandle>> relDefinesByProperties in relDefinesByPropertiesMap) { IFCInstanceExporter.CreateRelDefinesByProperties(file, GUIDUtil.CreateGUID(), ownerHistory, null, null, relDefinesByProperties.Value, relDefinesByProperties.Key); } transaction.Commit(); } if (ExporterCacheManager.ExportOptionsCache.ExportAs2x2) ExportPsetDraughtingFor2x2(exporterIFC, element, productWrapper); }
/// <summary> /// Collect information to create zones and cache them to create when end export. /// </summary> /// <param name="exporterIFC">The exporterIFC object.</param> /// <param name="file">The IFCFile object.</param> /// <param name="element">The element.</param> /// <param name="productWrapper">The ProductWrapper.</param> static void CreateZoneInfos(ExporterIFC exporterIFC, IFCFile file, Element element, ProductWrapper productWrapper) { bool exportToCOBIE = ExporterCacheManager.ExportOptionsCache.ExportAsCOBIE; // Extra zone information, since Revit doesn't have architectural zones. int val = 0; string basePropZoneName = "ZoneName"; string basePropZoneObjectType = "ZoneObjectType"; string basePropZoneDescription = "ZoneDescription"; string basePropZoneClassificationCode = "ZoneClassificationCode"; // While a room may contain multiple zones, only one can have the extra parameters. We will allow the first zone encountered // to be defined by them. If we require defining multiple zones in one room, then the code below should be modified to modify the // names of the shared parameters to include the index of the appropriate room. bool exportedExtraZoneInformation = false; while (++val < 1000) // prevent infinite loop. { string propZoneName, propZoneObjectType, propZoneDescription, propZoneClassificationCode; if (val == 1) { propZoneName = basePropZoneName; propZoneObjectType = basePropZoneObjectType; propZoneDescription = basePropZoneDescription; propZoneClassificationCode = basePropZoneClassificationCode; } else { propZoneName = basePropZoneName + " " + val; propZoneObjectType = basePropZoneObjectType + " " + val; propZoneDescription = basePropZoneDescription + " " + val; propZoneClassificationCode = basePropZoneClassificationCode + " " + val; } string zoneName; string zoneObjectType; string zoneDescription; string zoneClassificationCode; IFCAnyHandle zoneClassificationReference; if (ParameterUtil.GetOptionalStringValueFromElementOrSymbol(element, propZoneName, out zoneName) == null) break; // If we have an empty zone name, but the value exists, keep looking to make sure there aren't valid values later. if (!String.IsNullOrEmpty(zoneName)) { Dictionary<string, IFCAnyHandle> classificationHandles = new Dictionary<string, IFCAnyHandle>(); ParameterUtil.GetStringValueFromElementOrSymbol(element, propZoneObjectType, out zoneObjectType); ParameterUtil.GetStringValueFromElementOrSymbol(element, propZoneDescription, out zoneDescription); ParameterUtil.GetStringValueFromElementOrSymbol(element, propZoneClassificationCode, out zoneClassificationCode); string classificationName, classificationCode, classificationDescription; if (!String.IsNullOrEmpty(zoneClassificationCode)) { ClassificationUtil.parseClassificationCode(zoneClassificationCode, propZoneClassificationCode, out classificationName, out classificationCode, out classificationDescription); string location = null; ExporterCacheManager.ClassificationLocationCache.TryGetValue(classificationName, out location); zoneClassificationReference = ClassificationUtil.CreateClassificationReference(file, classificationName, classificationCode, classificationDescription, location); classificationHandles.Add(classificationName, zoneClassificationReference); } IFCAnyHandle roomHandle = productWrapper.GetElementOfType(IFCEntityType.IfcSpace); IFCAnyHandle energyAnalysisPSetHnd = null; if (exportToCOBIE && !exportedExtraZoneInformation) { exportedExtraZoneInformation = CreateGSAInformation(exporterIFC, element, zoneObjectType, classificationHandles, energyAnalysisPSetHnd); } ZoneInfo zoneInfo = ExporterCacheManager.ZoneInfoCache.Find(zoneName); if (zoneInfo == null) { IFCAnyHandle zoneCommonPropertySetHandle = CreateZoneCommonPSet(exporterIFC, file, element); zoneInfo = new ZoneInfo(zoneObjectType, zoneDescription, roomHandle, classificationHandles, energyAnalysisPSetHnd, zoneCommonPropertySetHandle); ExporterCacheManager.ZoneInfoCache.Register(zoneName, zoneInfo); } else { // if description and object type were empty, overwrite. if (!String.IsNullOrEmpty(zoneObjectType) && String.IsNullOrEmpty(zoneInfo.ObjectType)) zoneInfo.ObjectType = zoneObjectType; if (!String.IsNullOrEmpty(zoneDescription) && String.IsNullOrEmpty(zoneInfo.Description)) zoneInfo.Description = zoneDescription; zoneInfo.RoomHandles.Add(roomHandle); foreach (KeyValuePair<string, IFCAnyHandle> classificationReference in classificationHandles) { if (!zoneInfo.ClassificationReferences[classificationReference.Key].HasValue) zoneInfo.ClassificationReferences[classificationReference.Key] = classificationReference.Value; else { // Delete redundant IfcClassificationReference from file. classificationReference.Value.Delete(); } } if (IFCAnyHandleUtil.IsNullOrHasNoValue(zoneInfo.EnergyAnalysisProperySetHandle)) zoneInfo.EnergyAnalysisProperySetHandle = energyAnalysisPSetHnd; else if (energyAnalysisPSetHnd.HasValue) energyAnalysisPSetHnd.Delete(); if (IFCAnyHandleUtil.IsNullOrHasNoValue(zoneInfo.ZoneCommonProperySetHandle)) zoneInfo.ZoneCommonProperySetHandle = CreateZoneCommonPSet(exporterIFC, file, element); } } } }
private static void ExportElementClassifications(ExporterIFC exporterIFC, Element element, ProductWrapper productWrapper) { if (productWrapper.IsEmpty()) return; IFCFile file = exporterIFC.GetFile(); using (IFCTransaction transaction = new IFCTransaction(file)) { ICollection<IFCAnyHandle> productSet = productWrapper.GetAllObjects(); foreach (IFCAnyHandle prodHnd in productSet) { // No need to check the subtype since Classification can be assigned to IfcRoot // if (IFCAnyHandleUtil.IsSubTypeOf(prodHnd, IFCEntityType.IfcElement)) ClassificationUtil.CreateClassification(exporterIFC, file, element, prodHnd); } transaction.Commit(); } }
/// <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 a curve element to IFC curve annotation. /// </summary> /// <param name="exporterIFC"> /// The ExporterIFC object. /// </param> /// <param name="curveElement"> /// The curve element to be exported. /// </param> /// <param name="geometryElement"> /// The geometry element. /// </param> /// <param name="productWrapper"> /// The ProductWrapper. /// </param> public static void ExportCurveElement(ExporterIFC exporterIFC, CurveElement curveElement, GeometryElement geometryElement, ProductWrapper productWrapper) { if (geometryElement == null || !ShouldCurveElementBeExported(curveElement)) return; SketchPlane sketchPlane = curveElement.SketchPlane; if (sketchPlane == null) return; IFCFile file = exporterIFC.GetFile(); using (IFCTransaction transaction = new IFCTransaction(file)) { using (PlacementSetter setter = PlacementSetter.Create(exporterIFC, curveElement)) { IFCAnyHandle localPlacement = setter.LocalPlacement; IFCAnyHandle axisPlacement = GeometryUtil.GetRelativePlacementFromLocalPlacement(localPlacement); Plane planeSK = sketchPlane.GetPlane(); XYZ projDir = planeSK.Normal; XYZ origin = planeSK.Origin; bool useOffsetTrf = false; if (projDir.IsAlmostEqualTo(XYZ.BasisZ)) { XYZ offset = XYZ.BasisZ * setter.Offset; origin -= offset; } else useOffsetTrf = true; Plane plane = new Plane(planeSK.XVec, planeSK.YVec, origin); IFCGeometryInfo info = IFCGeometryInfo.CreateCurveGeometryInfo(exporterIFC, plane, projDir, false); if (useOffsetTrf) { XYZ offsetOrig = -XYZ.BasisZ * setter.Offset; Transform trf = Transform.CreateTranslation(offsetOrig); ExporterIFCUtils.CollectGeometryInfo(exporterIFC, info, geometryElement, XYZ.Zero, false, trf); } else { ExporterIFCUtils.CollectGeometryInfo(exporterIFC, info, geometryElement, XYZ.Zero, false); } IList<IFCAnyHandle> curves = info.GetCurves(); if (curves.Count != 1) { throw new Exception("IFC: expected 1 curve when export curve element."); } HashSet<IFCAnyHandle> curveSet = new HashSet<IFCAnyHandle>(curves); IFCAnyHandle repItemHnd = IFCInstanceExporter.CreateGeometricCurveSet(file, curveSet); IFCAnyHandle curveStyle = file.CreateStyle(exporterIFC, repItemHnd); CurveAnnotationCache annotationCache = ExporterCacheManager.CurveAnnotationCache; IFCAnyHandle curveAnno = annotationCache.GetAnnotation(sketchPlane.Id, curveStyle); if (!IFCAnyHandleUtil.IsNullOrHasNoValue(curveAnno)) { AddCurvesToAnnotation(curveAnno, curves); } else { curveAnno = CreateCurveAnnotation(exporterIFC, curveElement, curveElement.Category.Id, sketchPlane.Id, plane, curveStyle, setter, localPlacement, repItemHnd); productWrapper.AddAnnotation(curveAnno, setter.LevelInfo, true); annotationCache.AddAnnotation(sketchPlane.Id, curveStyle, curveAnno); } } transaction.Commit(); } }
/// <summary> /// Exports spatial elements, including rooms, areas and spaces. 1st level space boundaries. /// </summary> /// <param name="exporterIFC"> /// The ExporterIFC object. /// </param> /// <param name="spatialElement"> /// The spatial element. /// </param> /// <param name="productWrapper"> /// The ProductWrapper. /// </param> public static void ExportSpatialElement(ExporterIFC exporterIFC, SpatialElement spatialElement, ProductWrapper productWrapper) { IFCFile file = exporterIFC.GetFile(); using (IFCTransaction transaction = new IFCTransaction(file)) { using (PlacementSetter setter = PlacementSetter.Create(exporterIFC, spatialElement, null, null)) { SpatialElementGeometryResults spatialElemGeomResult = null; if (!CreateIFCSpace(exporterIFC, spatialElement, productWrapper, setter, out spatialElemGeomResult)) return; bool isArea = (spatialElement is Area); // Do not create boundary information for areas. if (!isArea && (ExporterCacheManager.ExportOptionsCache.SpaceBoundaryLevel == 1)) { Document document = spatialElement.Document; ElementId levelId = spatialElement.LevelId; IFCLevelInfo levelInfo = exporterIFC.GetLevelInfo(levelId); double baseHeightNonScaled = (levelInfo != null) ? levelInfo.Elevation : 0.0; try { // This can throw an exception. If it does, continue to export element without boundary information. // We will re-use the previously generated value, if we have it. // TODO: warn user. if (spatialElemGeomResult == null) spatialElemGeomResult = s_SpatialElementGeometryCalculator.CalculateSpatialElementGeometry(spatialElement); Solid spatialElemGeomSolid = spatialElemGeomResult.GetGeometry(); FaceArray faces = spatialElemGeomSolid.Faces; foreach (Face face in faces) { IList<SpatialElementBoundarySubface> spatialElemBoundarySubfaces = spatialElemGeomResult.GetBoundaryFaceInfo(face); foreach (SpatialElementBoundarySubface spatialElemBSubface in spatialElemBoundarySubfaces) { if (spatialElemBSubface.SubfaceType == SubfaceType.Side) continue; if (spatialElemBSubface.GetSubface() == null) continue; ElementId elemId = spatialElemBSubface.SpatialBoundaryElement.LinkInstanceId; if (elemId == ElementId.InvalidElementId) { elemId = spatialElemBSubface.SpatialBoundaryElement.HostElementId; } Element boundingElement = document.GetElement(elemId); if (boundingElement == null) continue; bool isObjectExt = CategoryUtil.IsElementExternal(boundingElement); IFCGeometryInfo info = IFCGeometryInfo.CreateSurfaceGeometryInfo(spatialElement.Document.Application.VertexTolerance); Face subFace = spatialElemBSubface.GetSubface(); ExporterIFCUtils.CollectGeometryInfo(exporterIFC, info, subFace, XYZ.Zero, false); foreach (IFCAnyHandle surfaceHnd in info.GetSurfaces()) { IFCAnyHandle connectionGeometry = IFCInstanceExporter.CreateConnectionSurfaceGeometry(file, surfaceHnd, null); SpaceBoundary spaceBoundary = new SpaceBoundary(spatialElement.Id, boundingElement.Id, setter.LevelId, connectionGeometry, IFCPhysicalOrVirtual.Physical, isObjectExt ? IFCInternalOrExternal.External : IFCInternalOrExternal.Internal); if (!ProcessIFCSpaceBoundary(exporterIFC, spaceBoundary, file)) ExporterCacheManager.SpaceBoundaryCache.Add(spaceBoundary); } } } } catch { } IList<IList<BoundarySegment>> roomBoundaries = spatialElement.GetBoundarySegments(GetSpatialElementBoundaryOptions(spatialElement)); double scaledRoomHeight = GetScaledHeight(spatialElement, levelId, levelInfo); double unscaledHeight = UnitUtil.UnscaleLength(scaledRoomHeight); Plane xyPlane = new Plane(XYZ.BasisZ, XYZ.Zero); foreach (IList<BoundarySegment> roomBoundaryList in roomBoundaries) { foreach (BoundarySegment roomBoundary in roomBoundaryList) { Element boundingElement = roomBoundary.Element; if (boundingElement == null) continue; ElementId buildingElemId = boundingElement.Id; Curve trimmedCurve = roomBoundary.Curve; if (trimmedCurve == null) continue; //trimmedCurve.Visibility = Visibility.Visible; readonly IFCAnyHandle connectionGeometry = ExtrusionExporter.CreateConnectionSurfaceGeometry( exporterIFC, trimmedCurve, xyPlane, scaledRoomHeight, baseHeightNonScaled); IFCPhysicalOrVirtual physOrVirt = IFCPhysicalOrVirtual.Physical; if (boundingElement is CurveElement) physOrVirt = IFCPhysicalOrVirtual.Virtual; else if (boundingElement is Autodesk.Revit.DB.Architecture.Room) physOrVirt = IFCPhysicalOrVirtual.NotDefined; bool isObjectExt = CategoryUtil.IsElementExternal(boundingElement); bool isObjectPhys = (physOrVirt == IFCPhysicalOrVirtual.Physical); ElementId actualBuildingElemId = isObjectPhys ? buildingElemId : ElementId.InvalidElementId; SpaceBoundary spaceBoundary = new SpaceBoundary(spatialElement.Id, actualBuildingElemId, setter.LevelId, !IFCAnyHandleUtil.IsNullOrHasNoValue(connectionGeometry) ? connectionGeometry : null, physOrVirt, isObjectExt ? IFCInternalOrExternal.External : IFCInternalOrExternal.Internal); if (!ProcessIFCSpaceBoundary(exporterIFC, spaceBoundary, file)) ExporterCacheManager.SpaceBoundaryCache.Add(spaceBoundary); // try to add doors and windows for host objects if appropriate. if (isObjectPhys && boundingElement is HostObject) { HostObject hostObj = boundingElement as HostObject; HashSet<ElementId> elemIds = new HashSet<ElementId>(); elemIds.UnionWith(hostObj.FindInserts(false, false, false, false)); if (elemIds.Count == 0) { CurtainGridSet curtainGridSet = CurtainSystemExporter.GetCurtainGridSet(hostObj); if (curtainGridSet != null) { foreach (CurtainGrid curtainGrid in curtainGridSet) elemIds.UnionWith(CurtainSystemExporter.GetVisiblePanelsForGrid(curtainGrid)); } } foreach (ElementId elemId in elemIds) { // we are going to do a simple bbox export, not complicated geometry. Element instElem = document.GetElement(elemId); if (instElem == null) continue; BoundingBoxXYZ instBBox = instElem.get_BoundingBox(null); if (instBBox == null) continue; // make copy of original trimmed curve. Curve instCurve = trimmedCurve.Clone(); XYZ instOrig = instCurve.GetEndPoint(0); // make sure that the insert is on this level. if (instBBox.Max.Z < instOrig.Z) continue; if (instBBox.Min.Z > instOrig.Z + unscaledHeight) continue; double insHeight = Math.Min(instBBox.Max.Z, instOrig.Z + unscaledHeight) - Math.Max(instOrig.Z, instBBox.Min.Z); if (insHeight < (1.0 / (12.0 * 16.0))) continue; // move base curve to bottom of bbox. XYZ moveDir = new XYZ(0.0, 0.0, instBBox.Min.Z - instOrig.Z); Transform moveTrf = Transform.CreateTranslation(moveDir); instCurve = instCurve.CreateTransformed(moveTrf); bool isHorizOrVert = false; if (instCurve is Line) { Line instLine = instCurve as Line; XYZ lineDir = instLine.Direction; if (MathUtil.IsAlmostEqual(Math.Abs(lineDir.X), 1.0) || (MathUtil.IsAlmostEqual(Math.Abs(lineDir.Y), 1.0))) isHorizOrVert = true; } double[] parameters = new double[2]; double[] origEndParams = new double[2]; bool paramsSet = false; if (!isHorizOrVert) { FamilyInstance famInst = instElem as FamilyInstance; if (famInst == null) continue; ElementType elementType = document.GetElement(famInst.GetTypeId()) as ElementType; if (elementType == null) continue; BoundingBoxXYZ symBBox = elementType.get_BoundingBox(null); if (symBBox != null) { Curve symCurve = trimmedCurve.Clone(); Transform trf = famInst.GetTransform(); Transform invTrf = trf.Inverse; Curve trfCurve = symCurve.CreateTransformed(invTrf); parameters[0] = trfCurve.Project(symBBox.Min).Parameter; parameters[1] = trfCurve.Project(symBBox.Max).Parameter; paramsSet = true; } } if (!paramsSet) { parameters[0] = instCurve.Project(instBBox.Min).Parameter; parameters[1] = instCurve.Project(instBBox.Max).Parameter; } // ignore if less than 1/16". if (Math.Abs(parameters[1] - parameters[0]) < 1.0 / (12.0 * 16.0)) continue; if (parameters[0] > parameters[1]) { //swap double tempParam = parameters[0]; parameters[0] = parameters[1]; parameters[1] = tempParam; } origEndParams[0] = instCurve.GetEndParameter(0); origEndParams[1] = instCurve.GetEndParameter(1); if (origEndParams[0] > parameters[1] - (1.0 / (12.0 * 16.0))) continue; if (origEndParams[1] < parameters[0] + (1.0 / (12.0 * 16.0))) continue; instCurve.MakeBound(parameters[0] > origEndParams[0] ? parameters[0] : origEndParams[0], parameters[1] < origEndParams[1] ? parameters[1] : origEndParams[1]); double insHeightScaled = UnitUtil.ScaleLength(insHeight); IFCAnyHandle insConnectionGeom = ExtrusionExporter.CreateConnectionSurfaceGeometry(exporterIFC, instCurve, xyPlane, insHeightScaled, baseHeightNonScaled); SpaceBoundary instBoundary = new SpaceBoundary(spatialElement.Id, elemId, setter.LevelId, !IFCAnyHandleUtil.IsNullOrHasNoValue(insConnectionGeom) ? insConnectionGeom : null, physOrVirt, isObjectExt ? IFCInternalOrExternal.External : IFCInternalOrExternal.Internal); if (!ProcessIFCSpaceBoundary(exporterIFC, instBoundary, file)) ExporterCacheManager.SpaceBoundaryCache.Add(instBoundary); } } } } } CreateZoneInfos(exporterIFC, file, spatialElement, productWrapper); CreateSpaceOccupantInfo(exporterIFC, file, spatialElement, productWrapper); } transaction.Commit(); } }
/// <summary> /// Exports a gutter element. /// </summary> /// <param name="exporterIFC">The ExporterIFC object.</param> /// <param name="element">The element.</param> /// <param name="geometryElement">The geometry element.</param> /// <param name="productWrapper">The ProductWrapper.</param> public static void ExportGutter(ExporterIFC exporterIFC, Element element, GeometryElement geometryElement, ProductWrapper productWrapper) { IFCFile file = exporterIFC.GetFile(); using (IFCTransaction tr = new IFCTransaction(file)) { using (PlacementSetter setter = PlacementSetter.Create(exporterIFC, element)) { using (IFCExtrusionCreationData ecData = new IFCExtrusionCreationData()) { ecData.SetLocalPlacement(setter.LocalPlacement); ElementId categoryId = CategoryUtil.GetSafeCategoryId(element); BodyExporterOptions bodyExporterOptions = new BodyExporterOptions(); IFCAnyHandle bodyRep = BodyExporter.ExportBody(exporterIFC, element, categoryId, ElementId.InvalidElementId, geometryElement, bodyExporterOptions, ecData).RepresentationHnd; if (IFCAnyHandleUtil.IsNullOrHasNoValue(bodyRep)) { if (ecData != null) ecData.ClearOpenings(); return; } IFCAnyHandle ownerHistory = exporterIFC.GetOwnerHistoryHandle(); string originalTag = NamingUtil.CreateIFCElementId(element); // In Revit, we don't have a corresponding type, so we create one for every gutter. IFCAnyHandle origin = ExporterUtil.CreateAxis2Placement3D(file); IFCAnyHandle repMap3dHnd = IFCInstanceExporter.CreateRepresentationMap(file, origin, bodyRep); List<IFCAnyHandle> repMapList = new List<IFCAnyHandle>(); repMapList.Add(repMap3dHnd); string elementTypeName = NamingUtil.CreateIFCObjectName(exporterIFC, element); string typeGuid = GUIDUtil.CreateSubElementGUID(element, (int) IFCHostedSweepSubElements.PipeSegmentType); IFCAnyHandle style = IFCInstanceExporter.CreatePipeSegmentType(file, typeGuid, ownerHistory, elementTypeName, null, null, null, repMapList, originalTag, elementTypeName, IFCPipeSegmentType.Gutter); List<IFCAnyHandle> representationMaps = GeometryUtil.GetRepresentationMaps(style); IFCAnyHandle mappedItem = ExporterUtil.CreateDefaultMappedItem(file, representationMaps[0]); ISet<IFCAnyHandle> representations = new HashSet<IFCAnyHandle>(); representations.Add(mappedItem); IFCAnyHandle bodyMappedItemRep = RepresentationUtil.CreateBodyMappedItemRep(exporterIFC, element, categoryId, exporterIFC.Get3DContextHandle("Body"), representations); if (IFCAnyHandleUtil.IsNullOrHasNoValue(bodyMappedItemRep)) return; List<IFCAnyHandle> shapeReps = new List<IFCAnyHandle>(); shapeReps.Add(bodyMappedItemRep); IFCAnyHandle boundingBoxRep = BoundingBoxExporter.ExportBoundingBox(exporterIFC, geometryElement, Transform.Identity); if (boundingBoxRep != null) shapeReps.Add(boundingBoxRep); IFCAnyHandle prodRep = IFCInstanceExporter.CreateProductDefinitionShape(file, null, null, shapeReps); IFCAnyHandle localPlacementToUse; ElementId roomId = setter.UpdateRoomRelativeCoordinates(element, out localPlacementToUse); if (roomId == ElementId.InvalidElementId) localPlacementToUse = ecData.GetLocalPlacement(); string guid = GUIDUtil.CreateGUID(element); string name = NamingUtil.GetNameOverride(element, NamingUtil.GetIFCName(element)); string description = NamingUtil.GetDescriptionOverride(element, null); string objectType = NamingUtil.GetObjectTypeOverride(element, elementTypeName); string tag = NamingUtil.GetTagOverride(element, originalTag); IFCAnyHandle elemHnd = IFCInstanceExporter.CreateFlowSegment(file, guid, ownerHistory, name, description, objectType, localPlacementToUse, prodRep, tag); bool containedInSpace = (roomId != ElementId.InvalidElementId); productWrapper.AddElement(element, elemHnd, setter.LevelInfo, ecData, !containedInSpace); if (containedInSpace) ExporterCacheManager.SpaceInfoCache.RelateToSpace(roomId, elemHnd); // Associate segment with type. ExporterCacheManager.TypeRelationsCache.Add(style, elemHnd); OpeningUtil.CreateOpeningsIfNecessary(elemHnd, element, ecData, null, exporterIFC, localPlacementToUse, setter, productWrapper); } tr.Commit(); } } }
/// <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); } } }