/// <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 IFCProductWrapper. /// </param> static void CreateSpaceOccupantInfo(ExporterIFC exporterIFC, IFCFile file, Element element, IFCProductWrapper productWrapper) { IFCAnyHandle roomHandle = null; ICollection<IFCAnyHandle> products = productWrapper.GetProducts(); if (products.Count == 0) return; else roomHandle = products.ElementAt(0); bool exportToCOBIE = ExporterCacheManager.ExportOptionsCache.FileVersion == IFCVersion.IFCCOBIE; string name; if (ParameterUtil.GetStringValueFromElement(element, "Occupant", out name)) { Dictionary<string, IFCAnyHandle> classificationHandles = new Dictionary<string, IFCAnyHandle>(); // Classifications. if (exportToCOBIE) { Document doc = element.Document; ProjectInfo projectInfo = doc.ProjectInformation; string location; ParameterUtil.GetStringValueFromElement(projectInfo, "BIM Standards URL", out location); string itemReference; if (ParameterUtil.GetStringValueFromElementOrSymbol(element, "Space Occupant Organization ID Reference", out itemReference)) { 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)) { 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)) { 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)) { 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> /// 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 IFCProductWrapper. /// </param> static void CreateZoneInfos(ExporterIFC exporterIFC, IFCFile file, Element element, IFCProductWrapper productWrapper) { bool exportToCOBIE = ExporterCacheManager.ExportOptionsCache.FileVersion == IFCVersion.IFCCOBIE; // Zone Information - For BCA / GSA int val = 0; string basePropZoneName = "ZoneName"; string basePropZoneObjectType = "ZoneObjectType"; string basePropZoneDescription = "ZoneDescription"; // While a room may contain multiple zones, only one can have the extra GSA 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; if (val == 1) { propZoneName = basePropZoneName; propZoneObjectType = basePropZoneObjectType; propZoneDescription = basePropZoneDescription; } else { propZoneName = basePropZoneName + " " + val; propZoneObjectType = basePropZoneObjectType + " " + val; propZoneDescription = basePropZoneDescription + " " + val; } { string zoneName; string zoneObjectType; string zoneDescription; if (ParameterUtil.GetStringValueFromElementOrSymbol(element, propZoneName, out zoneName) && !String.IsNullOrEmpty(zoneName)) { ParameterUtil.GetStringValueFromElementOrSymbol(element, propZoneObjectType, out zoneObjectType); ParameterUtil.GetStringValueFromElementOrSymbol(element, propZoneDescription, out zoneDescription); IFCAnyHandle roomHandle = null; ICollection<IFCAnyHandle> products = productWrapper.GetProducts(); if (products.Count == 0) return; else roomHandle = products.ElementAt(0); Dictionary<string, IFCAnyHandle> classificationHandles = new Dictionary<string, IFCAnyHandle>(); IFCAnyHandle energyAnalysisPSetHnd = null; if (exportToCOBIE && !exportedExtraZoneInformation) { if (NamingUtil.IsEqualIgnoringCaseAndSpaces(zoneObjectType, "SpatialZone")) { // Classifications. Document doc = element.Document; ProjectInfo projectInfo = doc.ProjectInformation; string location; ParameterUtil.GetStringValueFromElement(projectInfo, "BIM Standards URL", out location); string itemReference; string itemName; // Spatial Zone Type (Owner) if (ParameterUtil.GetStringValueFromElementOrSymbol(element, "Spatial Zone Type (Owner) Reference", out itemReference)) { ParameterUtil.GetStringValueFromElementOrSymbol(element, "Spatial Zone Type (Owner) Name", out itemName); IFCAnyHandle classificationReference = IFCInstanceExporter.CreateClassificationReference(file, location, itemReference, itemName, null); classificationHandles["Spatial Zone Type (Owner)"] = classificationReference; } // Spatial Zone Security Level (Owner) if (ParameterUtil.GetStringValueFromElementOrSymbol(element, "Spatial Zone Security Level (Owner) Reference", out itemReference)) { itemName = ""; ParameterUtil.GetStringValueFromElementOrSymbol(element, "Spatial Zone Security Level (Owner) Name", out itemName); IFCAnyHandle classificationReference = IFCInstanceExporter.CreateClassificationReference(file, location, itemReference, itemName, null); classificationHandles["Spatial Zone Security Level (Owner)"] = classificationReference; } // Spatial Zone Type (Energy Analysis) if (ParameterUtil.GetStringValueFromElementOrSymbol(element, "ASHRAE Zone Type", out itemName)) { IFCAnyHandle classificationReference = IFCInstanceExporter.CreateClassificationReference(file, "ASHRAE 90.1", "Common Space Type", itemName, null); classificationHandles["ASHRAE Zone Type"] = classificationReference; } // Property Sets. We don't use the generic Property Set mechanism because Zones aren't "real" elements. energyAnalysisPSetHnd = CreateSpatialZoneEnergyAnalysisPSet(exporterIFC, file, element); if (classificationHandles.Count > 0 || energyAnalysisPSetHnd != null) exportedExtraZoneInformation = true; } } ZoneInfo zoneInfo = ExporterCacheManager.ZoneInfoCache.Find(zoneName); if (zoneInfo == null) { zoneInfo = new ZoneInfo(zoneObjectType, zoneDescription, roomHandle, classificationHandles, energyAnalysisPSetHnd); 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 (zoneInfo.EnergyAnalysisProperySetHandle == null || !zoneInfo.EnergyAnalysisProperySetHandle.HasValue) zoneInfo.EnergyAnalysisProperySetHandle = energyAnalysisPSetHnd; else if (energyAnalysisPSetHnd.HasValue) energyAnalysisPSetHnd.Delete(); } } else break; } } }
/// <summary> /// Creates property sets for Revit groups and parameters, if export options is set. /// </summary> /// <param name="exporterIFC"> /// The ExporterIFC. /// </param> /// <param name="element"> /// The Element. /// </param> /// <param name="productWrapper"> /// The product wrapper. /// </param> public static void CreateInternalRevitPropertySets(ExporterIFC exporterIFC, Element element, IFCProductWrapper productWrapper) { if (exporterIFC == null || element == null || productWrapper == null || !ExporterCacheManager.ExportOptionsCache.ExportInternalRevitPropertySets) return; IFCFile file = exporterIFC.GetFile(); ICollection<IFCAnyHandle> elements = productWrapper.GetElements(); if (elements.Count == 0) { elements = productWrapper.GetProducts(); if (elements.Count == 0) return; } HashSet<IFCAnyHandle> elementSets = new HashSet<IFCAnyHandle>(elements); double lengthScale = exporterIFC.LinearScale; double angleScale = 180.0 / Math.PI; ElementId typeId = element.GetTypeId(); Element elementType = element.Document.GetElement(typeId); int whichStart = elementType != null ? 0 : (element is ElementType ? 1 : 0); if (whichStart == 1) elementType = element as ElementType; Dictionary<BuiltInParameterGroup, int>[] propertyArrIdxMap; propertyArrIdxMap = new Dictionary<BuiltInParameterGroup, int>[2]; // one for instance, one for type. propertyArrIdxMap[0] = new Dictionary<BuiltInParameterGroup, int>(); propertyArrIdxMap[1] = new Dictionary<BuiltInParameterGroup, int>(); List<HashSet<IFCAnyHandle>>[] propertyArr; propertyArr = new List<HashSet<IFCAnyHandle>>[2]; propertyArr[0] = new List<HashSet<IFCAnyHandle>>(); propertyArr[1] = new List<HashSet<IFCAnyHandle>>(); List<string>[] propertySetNames; propertySetNames = new List<string>[2]; propertySetNames[0] = new List<string>(); propertySetNames[1] = new List<string>(); // pass through: element and element type. If the element is a ElementType, there will only be one pass. for (int which = whichStart; which < 2; which++) { Element whichElement = (which == 0) ? element : elementType; if (whichElement == null) continue; bool createType = (which == 1); if (createType) { if (ExporterCacheManager.TypePropertyInfoCache.HasTypeProperties(typeId)) { ExporterCacheManager.TypePropertyInfoCache.AddTypeProperties(typeId, elementSets); continue; } } bool canUseElementType = ((which == 1) && elementType != null); ParameterSet parameters = whichElement.Parameters; foreach (Parameter parameter in parameters) { Definition parameterDefinition = parameter.Definition; if (parameterDefinition == null) continue; // IFC parameters dealt with separately. // TODO: also sort out parameters passed in Common Psets. BuiltInParameterGroup parameterGroup = parameterDefinition.ParameterGroup; if (parameterGroup == BuiltInParameterGroup.PG_IFC) continue; int idx = -1; if (!propertyArrIdxMap[which].TryGetValue(parameterGroup, out idx)) { idx = propertyArr[which].Count; propertyArrIdxMap[which][parameterGroup] = idx; propertyArr[which].Add(new HashSet<IFCAnyHandle>()); string groupName = LabelUtils.GetLabelFor(parameterGroup); propertySetNames[which].Add(groupName); } string parameterCaption = parameterDefinition.Name; switch (parameter.StorageType) { case StorageType.None: break; case StorageType.Integer: { int value; if (parameter.HasValue) value = parameter.AsInteger(); else { if (!canUseElementType) continue; Parameter elementTypeParameter = elementType.get_Parameter(parameterDefinition); if (elementTypeParameter != null && elementTypeParameter.HasValue && elementTypeParameter.StorageType == StorageType.Integer) value = elementTypeParameter.AsInteger(); else continue; } // YesNo or actual integer? if (parameterDefinition.ParameterType == ParameterType.YesNo) { propertyArr[which][idx].Add(CreateBooleanPropertyFromCache(file, parameterCaption, value != 0, PropertyValueType.SingleValue)); } else { propertyArr[which][idx].Add(CreateIntegerPropertyFromCache(file, parameterCaption, value, PropertyValueType.SingleValue)); } break; } case StorageType.Double: { double value = -1.0; if (parameter.HasValue) value = parameter.AsDouble(); else { if (!canUseElementType) continue; Parameter elementTypeParameter = elementType.get_Parameter(parameterDefinition); if (elementTypeParameter != null && elementTypeParameter.HasValue && elementTypeParameter.StorageType == StorageType.Double) value = elementTypeParameter.AsDouble(); else continue; } bool assigned = false; switch (parameterDefinition.ParameterType) { case ParameterType.Length: { propertyArr[which][idx].Add(CreateLengthMeasurePropertyFromCache(file, lengthScale, parameterCaption, value * lengthScale, PropertyValueType.SingleValue)); assigned = true; break; } case ParameterType.Angle: { propertyArr[which][idx].Add(CreatePlaneAngleMeasurePropertyFromCache(file, parameterCaption, value * angleScale, PropertyValueType.SingleValue)); assigned = true; break; } case ParameterType.Area: { propertyArr[which][idx].Add(CreateAreaMeasureProperty(file, parameterCaption, value * lengthScale * lengthScale, PropertyValueType.SingleValue)); assigned = true; break; } case ParameterType.Volume: { propertyArr[which][idx].Add(CreateVolumeMeasureProperty(file, parameterCaption, value * lengthScale * lengthScale * lengthScale, PropertyValueType.SingleValue)); assigned = true; break; } } if (!assigned) { propertyArr[which][idx].Add(CreateRealPropertyFromCache(file, lengthScale, parameterCaption, value, PropertyValueType.SingleValue)); } break; } case StorageType.String: { string value; if (parameter.HasValue) value = parameter.AsString(); else { if (!canUseElementType) continue; Parameter elementTypeParameter = elementType.get_Parameter(parameterDefinition); if (elementTypeParameter != null && elementTypeParameter.HasValue && elementTypeParameter.StorageType == StorageType.String) value = elementTypeParameter.AsString(); else continue; } propertyArr[which][idx].Add(CreateLabelPropertyFromCache(file, parameterCaption, value, PropertyValueType.SingleValue, false)); break; } case StorageType.ElementId: { ElementId value = ElementId.InvalidElementId; if (parameter.HasValue) value = parameter.AsElementId(); if (value == ElementId.InvalidElementId) { if (!canUseElementType) continue; Parameter elementTypeParameter = elementType.get_Parameter(parameterDefinition); if (elementTypeParameter != null && elementTypeParameter.HasValue && elementTypeParameter.StorageType == StorageType.ElementId) value = elementTypeParameter.AsElementId(); else continue; if (value == ElementId.InvalidElementId) continue; } Element paramElement = element.Document.GetElement(value); string valueString; if (paramElement != null && !string.IsNullOrEmpty(paramElement.Name)) { valueString = paramElement.Name; ElementType paramElementType = paramElement is ElementType ? paramElement as ElementType : element.Document.GetElement(paramElement.GetTypeId()) as ElementType; if (paramElementType != null && !string.IsNullOrEmpty(ExporterIFCUtils.GetFamilyName(paramElementType))) valueString = ExporterIFCUtils.GetFamilyName(paramElementType) + ": " + valueString; } else valueString = value.ToString(); propertyArr[which][idx].Add(CreateLabelPropertyFromCache(file, parameterCaption, valueString, PropertyValueType.SingleValue, true)); break; } } } } for (int which = whichStart; which < 2; which++) { HashSet<IFCAnyHandle> propertySets = new HashSet<IFCAnyHandle>(); int size = propertyArr[which].Count; if (size == 0) continue; for (int ii = 0; ii < size; ii++) { if (propertyArr[which][ii].Count == 0) continue; IFCAnyHandle propertySet = IFCInstanceExporter.CreatePropertySet(file, ExporterIFCUtils.CreateGUID(), exporterIFC.GetOwnerHistoryHandle(), propertySetNames[which][ii], null, propertyArr[which][ii]); if (which == 1) propertySets.Add(propertySet); else IFCInstanceExporter.CreateRelDefinesByProperties(file, ExporterIFCUtils.CreateGUID(), exporterIFC.GetOwnerHistoryHandle(), null, null, elementSets, propertySet); } if (which == 1) ExporterCacheManager.TypePropertyInfoCache.AddNewTypeProperties(typeId, propertySets, elementSets); } }