private void CalculateDoorWindowInformation(ExporterIFC exporterIFC, FamilyInstance famInst, ElementId overrideLevelId, Transform trf) { IFCFile file = exporterIFC.GetFile(); if (ExportingDoor) { string doorOperationType = null; Element doorType = famInst.Document.GetElement(famInst.GetTypeId()); if (doorType != null) { // Look at the "Operation" override first, then the built-in parameter. ParameterUtil.GetStringValueFromElementOrSymbol(doorType, "Operation", out doorOperationType); if (string.IsNullOrWhiteSpace(doorOperationType)) { ParameterUtil.GetStringValueFromElement(doorType, BuiltInParameter.DOOR_OPERATION_TYPE, out doorOperationType); } } DoorOperationTypeString = "NOTDEFINED"; if (!string.IsNullOrWhiteSpace(doorOperationType)) { Type enumType = null; if (ExporterCacheManager.ExportOptionsCache.ExportAs4) { enumType = typeof(Toolkit.IFC4.IFCDoorStyleOperation); } else { enumType = typeof(Toolkit.IFCDoorStyleOperation); } foreach (Enum ifcDoorStyleOperation in Enum.GetValues(enumType)) { string enumAsString = ifcDoorStyleOperation.ToString(); if (NamingUtil.IsEqualIgnoringCaseSpacesAndUnderscores(enumAsString, doorOperationType)) { DoorOperationTypeString = enumAsString; break; } } } if (DoorOperationTypeString == "NOTDEFINED") { // We are going to try to guess the hinge placement. DoorOperationTypeString = CalculateDoorOperationStyle(famInst, trf); } else { if (FlippedX ^ FlippedY) { DoorOperationTypeString = ReverseDoorStyleOperation(DoorOperationTypeString); } } if (String.Compare(DoorOperationTypeString, "USERDEFINED", true) == 0) { string userDefinedOperationType; ParameterUtil.GetStringValueFromElementOrSymbol(doorType, "UserDefinedOperationType", out userDefinedOperationType); if (!string.IsNullOrEmpty(userDefinedOperationType)) { UserDefinedOperationType = userDefinedOperationType; } else { DoorOperationTypeString = "NOTDEFINED"; //re-set to NotDefined if operation type is set to UserDefined but the userDefinedOperationType parameter is empty! } } } if (HasRealWallHost) { // do hingeside calculation Wall wall = HostObject as Wall; PosHingeSide = true; BoundingBoxXYZ famBBox = null; Options options = GeometryUtil.GetIFCExportGeometryOptions(); GeometryElement geomElement = famInst.GetOriginalGeometry(options); if (geomElement != null) { famBBox = geomElement.GetBoundingBox(); } if (famBBox != null) { XYZ bboxCtr = trf.OfPoint((famBBox.Min + famBBox.Max) / 2.0); Curve curve = WallExporter.GetWallAxis(wall); XYZ wallZDir = WallExporter.GetWallHeightDirection(wall); // famInst.HostParameter will fail if FamilyPlacementType is WorkPlaneBased, regardless of whether or not the reported host is a Wall. // In this case, just use the start parameter of the curve. bool hasHostParameter = famInst.Symbol.Family.FamilyPlacementType != FamilyPlacementType.WorkPlaneBased; double param = hasHostParameter ? famInst.HostParameter : curve.GetEndParameter(0); Transform wallTrf = curve.ComputeDerivatives(param, false); XYZ wallOrig = wallTrf.Origin; XYZ wallXDir = wallTrf.BasisX; XYZ wallYDir = wallZDir.CrossProduct(wallXDir); double eps = MathUtil.Eps(); bboxCtr -= wallOrig; PosHingeSide = (bboxCtr.DotProduct(wallYDir) > -eps); XYZ famInstYDir = trf.BasisY; FlippedSymbol = (PosHingeSide != (wallYDir.DotProduct(famInstYDir) > -eps)); } } }
/// <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 = ExporterCacheManager.OwnerHistoryHandle; 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); 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; } 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 = ExporterCacheManager.OwnerHistoryHandle; 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); } } }
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; } if (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. double matWidth = MaterialIds[ii].m_matWidth; 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) { IFCAnyHandle singleMaterialOverrideHnd = ExporterUtil.GetSingleMaterial(m_ExporterIFC, m_Element, MaterialIds[0].m_baseMatId); if (singleMaterialOverrideHnd != null) { m_MaterialLayerSetHandle = singleMaterialOverrideHnd; } else { m_MaterialLayerSetHandle = 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> /// 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, ExportOptionsCache.ExportTessellationLevel.ExtraLow); 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 = ExporterCacheManager.OwnerHistoryHandle; 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> /// Collect information about material layer. /// For IFC4RV Architectural exchange, it will generate IfcMatrialConstituentSet along with the relevant IfcShapeAspect and the width in the quantityset /// For IFC4RV Structural exchange, it will generate multiple components as IfcBuildingElementPart for each layer /// For others IfcMaterialLayer will be created /// </summary> private void CollectMaterialLayerSet() { ElementId typeElemId = m_Element.GetTypeId(); IFCAnyHandle materialLayerSet = ExporterCacheManager.MaterialSetCache.FindLayerSet(typeElemId); // Roofs with no components are only allowed one material. We will arbitrarily choose the thickest material. m_PrimaryMaterialHandle = ExporterCacheManager.MaterialSetCache.FindPrimaryMaterialHnd(typeElemId); bool materialHandleIsNotValid = IFCAnyHandleUtil.IsNullOrHasNoValue(materialLayerSet); if (IFCAnyHandleUtil.IsNullOrHasNoValue(materialLayerSet) || materialHandleIsNotValid) { if (materialHandleIsNotValid) { UnregisterIFCHandles(); } m_needToGenerateIFCObjects = true; List <double> widths = new List <double>(); List <MaterialFunctionAssignment> functions = new List <MaterialFunctionAssignment>(); HostObjAttributes hostObjAttr = m_Element.Document.GetElement(typeElemId) as HostObjAttributes; if (hostObjAttr == null) { // It does not have the HostObjAttribute (where we will get the compound structure for material layer set. // We will define a single material instead and create the material layer set of this single material if there is enough information (At least Material id and thickness) FamilyInstance familyInstance = m_Element as FamilyInstance; if (familyInstance == null) { return; } FamilySymbol familySymbol = familyInstance.Symbol; ICollection <ElementId> famMatIds = familySymbol.GetMaterialIds(false); if (famMatIds.Count == 0) { // For some reason Plate type may not return any Material id ElementId baseMatId = CategoryUtil.GetBaseMaterialIdForElement(m_Element); Material material = m_Element.Document.GetElement(baseMatId) as Material; if (material == null) { return; } string layerName = NamingUtil.GetMaterialLayerName(material); double matWidth = 0.0; Parameter thicknessPar = familySymbol.get_Parameter(BuiltInParameter.CURTAIN_WALL_SYSPANEL_THICKNESS); if (thicknessPar != null) { matWidth = thicknessPar.AsDouble(); } widths.Add(matWidth); if (baseMatId != ElementId.InvalidElementId) { MaterialIds.Add(new MaterialInfo(baseMatId, layerName, matWidth, MaterialFunctionAssignment.None)); } // How to get the thickness? For CurtainWall Panel (PanelType), there is a builtin parameter CURTAINWALL_SYSPANEL_THICKNESS functions.Add(MaterialFunctionAssignment.None); } else { foreach (ElementId matid in famMatIds) { // How to get the thickness? For CurtainWall Panel (PanelType), there is a builtin parameter CURTAINWALL_SYSPANEL_THICKNESS Parameter thicknessPar = familySymbol.get_Parameter(BuiltInParameter.CURTAIN_WALL_SYSPANEL_THICKNESS); double matWidth = 0.0; if (thicknessPar == null) { matWidth = ParameterUtil.GetSpecialThicknessParameter(familySymbol); } else { matWidth = thicknessPar.AsDouble(); } if (MathUtil.IsAlmostZero(matWidth)) { continue; } widths.Add(matWidth); ElementId baseMatId = CategoryUtil.GetBaseMaterialIdForElement(m_Element); if (matid != ElementId.InvalidElementId) { Material material = m_Element.Document.GetElement(matid) as Material; if (material != null) { string layerName = NamingUtil.GetMaterialLayerName(material); MaterialIds.Add(new MaterialInfo(matid, layerName, matWidth, MaterialFunctionAssignment.None)); } } else { MaterialIds.Add(new MaterialInfo(baseMatId, null, matWidth, MaterialFunctionAssignment.None)); } functions.Add(MaterialFunctionAssignment.None); } } } else { ElementId baseMatId = CategoryUtil.GetBaseMaterialIdForElement(m_Element); CompoundStructure cs = hostObjAttr.GetCompoundStructure(); if (cs != null) { double scaledOffset = 0.0, scaledWallWidth = 0.0, wallHeight = 0.0; Wall wall = m_Element 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; } } //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 ii = 0; ii < cs.LayerCount; ++ii) { double matWidth = cs.GetLayerWidth(ii); //if (MathUtil.IsAlmostZero(matWidth)) // continue; ElementId matId = cs.GetMaterialId(ii); widths.Add(matWidth); // save layer function into ProductWrapper, // it's used while exporting "Function" of Pset_CoveringCommon functions.Add(cs.GetLayerFunction(ii)); if (matId != ElementId.InvalidElementId) { Material material = m_Element.Document.GetElement(matId) as Material; if (material != null) { string layerName = NamingUtil.GetMaterialLayerName(material); MaterialIds.Add(new MaterialInfo(matId, layerName, matWidth, functions.Last())); } } else { MaterialIds.Add(new MaterialInfo(baseMatId, null, matWidth, functions.Last())); } } } if (MaterialIds.Count == 0) { double matWidth = cs != null?cs.GetWidth() : 0.0; widths.Add(matWidth); if (baseMatId != ElementId.InvalidElementId) { Material material = m_Element.Document.GetElement(baseMatId) as Material; if (material != null) { string layerName = NamingUtil.GetMaterialLayerName(material); MaterialIds.Add(new MaterialInfo(baseMatId, layerName, matWidth, MaterialFunctionAssignment.None)); } } functions.Add(MaterialFunctionAssignment.None); } } } else { m_needToGenerateIFCObjects = false; m_MaterialLayerSetHandle = materialLayerSet; MaterialLayerSetInfo mlsInfo = ExporterCacheManager.MaterialSetCache.FindMaterialLayerSetInfo(typeElemId); if (mlsInfo != null) { MaterialIds = mlsInfo.MaterialIds; m_PrimaryMaterialHandle = mlsInfo.PrimaryMaterialHandle; m_LayerQuantityWidthHnd = mlsInfo.LayerQuantityWidthHnd; } } return; }
/// <summary> /// Cache the parameters for an element's subelement (subelementHandle), allowing quick access later. /// </summary> /// <param name="elementId">The element id.</param> /// <param name="subelementHandle">The subelement ifc handle.</param> /// <param name="param">The element's parameter that we want to override.</param> /// <param name="paramVal">The override value.</param> static public void CacheParameterValuesForSubelementHandle(ElementId elementId, IFCAnyHandle subelementHandle, Parameter param, ParameterValue paramVal) { if ((elementId == ElementId.InvalidElementId) || (subelementHandle == null) || (param == null) || (paramVal == null)) { return; } if (IsDuplicateParameter(param)) { return; } Definition paramDefinition = param.Definition; if (paramDefinition == null) { return; } // Don't cache parameters that aren't visible to the user. InternalDefinition internalDefinition = paramDefinition as InternalDefinition; if (internalDefinition != null && internalDefinition.Visible == false) { return; } if (string.IsNullOrWhiteSpace(paramDefinition.Name)) { return; } string cleanPropertyName = NamingUtil.RemoveSpaces(paramDefinition.Name); IDictionary <IFCAnyHandle, ParameterValueSubelementCache> anyHandleParamValMap; if (!m_SubelementParameterValueCache.TryGetValue(elementId, out anyHandleParamValMap)) { anyHandleParamValMap = new Dictionary <IFCAnyHandle, ParameterValueSubelementCache>(); m_SubelementParameterValueCache[elementId] = anyHandleParamValMap; } ParameterValueSubelementCache paramCache; if (!anyHandleParamValMap.TryGetValue(subelementHandle, out paramCache)) { paramCache = new ParameterValueSubelementCache(); anyHandleParamValMap[subelementHandle] = paramCache; } ParameterValue cachedParamVal; if (paramCache.ParameterValueCache.TryGetValue(cleanPropertyName, out cachedParamVal)) { return; } paramCache.ParameterValueCache[cleanPropertyName] = paramVal; }
/// <summary> /// Cache the parameters for an element, allowing quick access later. /// </summary> /// <param name="id">The element id.</param> static private void CacheParametersForElement(ElementId id) { if (id == ElementId.InvalidElementId) { return; } if (m_NonIFCParameters.ContainsKey(id)) { return; } IDictionary <BuiltInParameterGroup, ParameterElementCache> nonIFCParameters = new SortedDictionary <BuiltInParameterGroup, ParameterElementCache>(); ParameterElementCache ifcParameters = new ParameterElementCache(); m_NonIFCParameters[id] = nonIFCParameters; m_IFCParameters[id] = ifcParameters; Element element = ExporterCacheManager.Document.GetElement(id); if (element == null) { return; } ParameterSet parameterIds = element.Parameters; if (parameterIds.Size == 0) { return; } // We will do two passes. In the first pass, we will look at parameters in the IFC group. // In the second pass, we will look at all other groups. ParameterSetIterator parameterIt = parameterIds.ForwardIterator(); while (parameterIt.MoveNext()) { Parameter parameter = parameterIt.Current as Parameter; if (parameter == null) { continue; } if (IsDuplicateParameter(parameter)) { continue; } Definition paramDefinition = parameter.Definition; if (paramDefinition == null) { continue; } // Don't cache parameters that aren't visible to the user. InternalDefinition internalDefinition = paramDefinition as InternalDefinition; if (internalDefinition != null && internalDefinition.Visible == false) { continue; } if (string.IsNullOrWhiteSpace(paramDefinition.Name)) { continue; } string cleanPropertyName = NamingUtil.RemoveSpaces(paramDefinition.Name); BuiltInParameterGroup groupId = paramDefinition.ParameterGroup; if (groupId != BuiltInParameterGroup.PG_IFC) { ParameterElementCache cacheForGroup = null; if (!nonIFCParameters.TryGetValue(groupId, out cacheForGroup)) { cacheForGroup = new ParameterElementCache(); nonIFCParameters[groupId] = cacheForGroup; } cacheForGroup.ParameterCache[cleanPropertyName] = parameter; } else { ifcParameters.ParameterCache[cleanPropertyName] = parameter; } } }
/// <summary> /// Gets material handle from material id or creates one if there is none. /// </summary> /// <param name="exporterIFC">The ExporterIFC object.</param> /// <param name="materialId">The material id.</param> /// <returns>The handle.</returns> public static IFCAnyHandle GetOrCreateMaterialHandle(ExporterIFC exporterIFC, ElementId materialId) { Document document = ExporterCacheManager.Document; IFCAnyHandle materialNameHandle = ExporterCacheManager.MaterialHandleCache.Find(materialId); if (IFCAnyHandleUtil.IsNullOrHasNoValue(materialNameHandle)) { string materialName = " <Unnamed>"; string description = null; string category = null; if (materialId != ElementId.InvalidElementId) { Material material = document.GetElement(materialId) as Material; if (material != null) { materialName = NamingUtil.GetNameOverride(material, material.Name); } if (ExporterCacheManager.ExportOptionsCache.ExportAs4) { category = NamingUtil.GetOverrideStringValue(material, "IfcCategory", NamingUtil.GetOverrideStringValue(material, "Category", material.MaterialCategory)); description = NamingUtil.GetOverrideStringValue(material, "IfcDescription", null); } } materialNameHandle = IFCInstanceExporter.CreateMaterial(exporterIFC.GetFile(), materialName, description: description, category: category); ExporterCacheManager.MaterialHandleCache.Register(materialId, materialNameHandle); // associate Material with SurfaceStyle if necessary. IFCFile file = exporterIFC.GetFile(); if (materialId != ElementId.InvalidElementId && !ExporterCacheManager.ExportOptionsCache.ExportAs2x2 && materialNameHandle.HasValue) { HashSet <IFCAnyHandle> matRepHandles = IFCAnyHandleUtil.GetHasRepresentation(materialNameHandle); if (matRepHandles.Count == 0) { Material matElem = document.GetElement(materialId) as Material; // TODO_DOUBLE_PATTERN - deal with background pattern ElementId fillPatternId = (matElem != null) ? matElem.CutForegroundPatternId : ElementId.InvalidElementId; Autodesk.Revit.DB.Color color = (matElem != null) ? GetSafeColor(matElem.CutForegroundPatternColor) : new Color(0, 0, 0); double planScale = 100.0; HashSet <IFCAnyHandle> styles = new HashSet <IFCAnyHandle>(); bool hasFill = false; IFCAnyHandle styledRepItem = null; IFCAnyHandle matStyleHnd = CategoryUtil.GetOrCreateMaterialStyle(document, exporterIFC, materialId); if (!IFCAnyHandleUtil.IsNullOrHasNoValue(matStyleHnd) && !ExporterCacheManager.ExportOptionsCache.ExportAs4ReferenceView) { styles.Add(matStyleHnd); bool supportCutStyles = !ExporterCacheManager.ExportOptionsCache.ExportAsCoordinationView2; if (fillPatternId != ElementId.InvalidElementId && supportCutStyles) { IFCAnyHandle cutStyleHnd = exporterIFC.GetOrCreateFillPattern(fillPatternId, color, planScale); if (cutStyleHnd.HasValue) { styles.Add(cutStyleHnd); hasFill = true; } } IFCAnyHandle presStyleHnd = IFCInstanceExporter.CreatePresentationStyleAssignment(file, styles); HashSet <IFCAnyHandle> presStyleSet = new HashSet <IFCAnyHandle>(); presStyleSet.Add(presStyleHnd); IFCAnyHandle styledItemHnd = IFCInstanceExporter.CreateStyledItem(file, styledRepItem, presStyleSet, null); IFCAnyHandle contextOfItems = exporterIFC.Get3DContextHandle(""); string repId = "Style"; string repType = (hasFill) ? "Material and Cut Pattern" : "Material"; HashSet <IFCAnyHandle> repItems = new HashSet <IFCAnyHandle>(); repItems.Add(styledItemHnd); IFCAnyHandle styleRepHnd = IFCInstanceExporter.CreateStyledRepresentation(file, contextOfItems, repId, repType, repItems); List <IFCAnyHandle> repList = new List <IFCAnyHandle>(); repList.Add(styleRepHnd); IFCAnyHandle matDefRepHnd = IFCInstanceExporter.CreateMaterialDefinitionRepresentation(file, null, null, repList, materialNameHandle); } } } } return(materialNameHandle); }
/// <summary> /// Cache the parameters for an element, allowing quick access later. /// </summary> /// <param name="id">The element id.</param> static private void CacheParametersForElement(ElementId id) { if (id == ElementId.InvalidElementId) { return; } if (m_NonIFCParameters.ContainsKey(id)) { return; } IDictionary <BuiltInParameterGroup, ParameterElementCache> nonIFCParameters = new SortedDictionary <BuiltInParameterGroup, ParameterElementCache>(); ParameterElementCache ifcParameters = new ParameterElementCache(); m_NonIFCParameters[id] = nonIFCParameters; m_IFCParameters[id] = ifcParameters; Element element = ExporterCacheManager.Document.GetElement(id); if (element == null) { return; } ParameterSet parameterIds = element.Parameters; if (parameterIds.Size == 0) { return; } // We will do two passes. In the first pass, we will look at parameters in the IFC group. // In the second pass, we will look at all other groups. ParameterSetIterator parameterIt = parameterIds.ForwardIterator(); while (parameterIt.MoveNext()) { Parameter parameter = parameterIt.Current as Parameter; if (parameter == null) { continue; } if (IsDuplicateParameter(parameter)) { continue; } Definition paramDefinition = parameter.Definition; if (paramDefinition == null) { continue; } // Don't cache parameters that aren't visible to the user. InternalDefinition internalDefinition = paramDefinition as InternalDefinition; if (internalDefinition != null && internalDefinition.Visible == false) { continue; } if (string.IsNullOrWhiteSpace(paramDefinition.Name)) { continue; } string cleanPropertyName = NamingUtil.RemoveSpaces(paramDefinition.Name); BuiltInParameterGroup groupId = paramDefinition.ParameterGroup; ParameterElementCache cacheForGroup = null; if (groupId != BuiltInParameterGroup.PG_IFC) { if (!nonIFCParameters.TryGetValue(groupId, out cacheForGroup)) { cacheForGroup = new ParameterElementCache(); nonIFCParameters[groupId] = cacheForGroup; } } else { cacheForGroup = ifcParameters; } if (cacheForGroup != null) { // We may have situations (due to bugs) where a parameter with the same name appears multiple times. // In this case, we will preserve the first parameter with a value. // Note that this can still cause inconsistent behavior in the case where multiple parameters with the same // name have values, and we should warn about that when we start logging. if (!cacheForGroup.ParameterCache.ContainsKey(cleanPropertyName) || !cacheForGroup.ParameterCache[cleanPropertyName].HasValue) { cacheForGroup.ParameterCache[cleanPropertyName] = parameter; } } } }