public MaterialConstituentCache() { MaterialConsituentInfoComparer comparer = new MaterialConsituentInfoComparer(); if (m_MaterialConstDictionary == null) { m_MaterialConstDictionary = new Dictionary <MaterialConstituentInfo, IFCAnyHandle>(comparer); } }
/// <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); } }