/// <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 association between a list of material handles and an instance handle, and create the relevant IfcShapeAspect /// </summary> /// <param name="exporterIFC">The ExporterIFC object.</param> /// <param name="element">The element</param> /// <param name="instanceHandle">The IFC instance handle.</param> /// <param name="representationItemInfoSet">RepresentationItem info set</param> public static void CreateMaterialAssociationWithShapeAspect(ExporterIFC exporterIFC, Element element, IFCAnyHandle instanceHandle, HashSet <Tuple <MaterialConstituentInfo, IFCAnyHandle> > representationItemInfoSet) { Document document = ExporterCacheManager.Document; // Create material association if any. bool createConstituentSet = (!ExporterCacheManager.ExportOptionsCache.ExportAsOlderThanIFC4); IList <IFCAnyHandle> materials = createConstituentSet ? null : new List <IFCAnyHandle>(); ISet <ElementId> alreadySeenMaterialIds = createConstituentSet ? new HashSet <ElementId>() : null; IFCAnyHandle matHnd = null; foreach (Tuple <MaterialConstituentInfo, IFCAnyHandle> repItemInfo in representationItemInfoSet) { matHnd = GetOrCreateMaterialHandle(exporterIFC, repItemInfo.Item1.MaterialId); if (IFCAnyHandleUtil.IsNullOrHasNoValue(matHnd)) { continue; } // Strictly speaking, we only need at most one material if createConstituentSet is true. if (createConstituentSet) { alreadySeenMaterialIds.Add(repItemInfo.Item1.MaterialId); } else { materials.Add(matHnd); } } int numMaterials = createConstituentSet ? alreadySeenMaterialIds.Count : materials.Count; if (numMaterials == 0) { return; } // If there is only one material, we will associate the one material directly. // matHnd above is guaranteed to have a valid value if numMaterials > 0. if (numMaterials == 1) { ExporterCacheManager.MaterialRelationsCache.Add(matHnd, instanceHandle); return; } IFCFile file = exporterIFC.GetFile(); IFCAnyHandle materialContainerHnd = null; if (createConstituentSet) { ExporterCacheManager.MaterialConstituentCache.Reset(); IDictionary <IFCAnyHandle, IFCAnyHandle> mapRepItemToItemDict = new Dictionary <IFCAnyHandle, IFCAnyHandle>(); string repType = null; IFCAnyHandle prodRep = null; if (IFCAnyHandleUtil.IsSubTypeOf(instanceHandle, IFCEntityType.IfcProduct)) { prodRep = IFCAnyHandleUtil.GetRepresentation(instanceHandle); IList <IFCAnyHandle> reps = IFCAnyHandleUtil.GetRepresentations(prodRep); // Get RepresentationType for shapeAspect in "Body" representation foreach (IFCAnyHandle rep in reps) { if (IFCAnyHandleUtil.GetRepresentationIdentifier(rep).Equals("Body")) { repType = IFCAnyHandleUtil.GetRepresentationType(rep); if (repType.Equals("MappedRepresentation", StringComparison.InvariantCultureIgnoreCase)) { HashSet <IFCAnyHandle> items = IFCAnyHandleUtil.GetItems(rep); foreach (IFCAnyHandle item in items) { IFCAnyHandle mappingSource = IFCAnyHandleUtil.GetInstanceAttribute(item, "MappingSource"); IFCAnyHandle mappingSourceRep = IFCAnyHandleUtil.GetInstanceAttribute(mappingSource, "MappedRepresentation"); repType = IFCAnyHandleUtil.GetRepresentationType(mappingSourceRep); } } break; } } } else if (IFCAnyHandleUtil.IsSubTypeOf(instanceHandle, IFCEntityType.IfcTypeProduct)) { IList <IFCAnyHandle> repMaps = IFCAnyHandleUtil.GetAggregateInstanceAttribute <List <IFCAnyHandle> >(instanceHandle, "RepresentationMaps"); if (repMaps != null && repMaps.Count > 0) { // Will use representation maps for shapeAspect if there is "Body" foreach (IFCAnyHandle repMap in repMaps) { IFCAnyHandle rep = IFCAnyHandleUtil.GetInstanceAttribute(repMap, "MappedRepresentation"); if (IFCAnyHandleUtil.GetRepresentationIdentifier(rep).Equals("Body")) { prodRep = repMap; repType = IFCAnyHandleUtil.GetRepresentationType(rep); break; } } } } // Collect ALL representationItems that have the same Category and MaterialId into one Set MaterialConsituentInfoComparer comparer = new MaterialConsituentInfoComparer(); IDictionary <MaterialConstituentInfo, HashSet <IFCAnyHandle> > repItemInfoGroup = new Dictionary <MaterialConstituentInfo, HashSet <IFCAnyHandle> >(comparer); foreach (Tuple <MaterialConstituentInfo, IFCAnyHandle> repItemInfo in representationItemInfoSet) { if (!repItemInfoGroup.ContainsKey(repItemInfo.Item1)) { HashSet <IFCAnyHandle> repItemSet = new HashSet <IFCAnyHandle>() { repItemInfo.Item2 }; repItemInfoGroup.Add(repItemInfo.Item1, repItemSet); } else { repItemInfoGroup[repItemInfo.Item1].Add(repItemInfo.Item2); } } HashSet <IFCAnyHandle> constituentSet = new HashSet <IFCAnyHandle>(); // in IFC4 we will create IfcConstituentSet instead of MaterialList, create the associated IfcConstituent here from IfcMaterial foreach (KeyValuePair <MaterialConstituentInfo, HashSet <IFCAnyHandle> > repItemInfoSet in repItemInfoGroup) { IFCAnyHandle constituentHnd = GetOrCreateMaterialConstituent(exporterIFC, repItemInfoSet.Key); if (!IFCAnyHandleUtil.IsNullOrHasNoValue(constituentHnd)) { constituentSet.Add(constituentHnd); } RepresentationUtil.CreateRepForShapeAspect(exporterIFC, element, prodRep, repType, repItemInfoSet.Key.ComponentCat, repItemInfoSet.Value); } if (constituentSet.Count > 0) { materialContainerHnd = GetOrCreateMaterialConstituentSet(file, instanceHandle, constituentSet); ExporterCacheManager.MaterialRelationsCache.Add(materialContainerHnd, instanceHandle); } } else { materialContainerHnd = CreateMaterialList(file, materials); ExporterCacheManager.MaterialSetUsageCache.Add(materialContainerHnd, instanceHandle); } }
/// <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 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); } } }