예제 #1
0
        /// <summary>
        /// Gets the material Id of the first layer of the host object.
        /// </summary>
        /// <param name="hostObject">The host object.</param>
        /// <returns>The material id.</returns>
        public static ElementId GetFirstLayerMaterialId(HostObject hostObject)
        {
            ElementId         typeElemId  = hostObject.GetTypeId();
            HostObjAttributes hostObjAttr = hostObject.Document.GetElement(typeElemId) as HostObjAttributes;

            if (hostObjAttr == null)
            {
                return(ElementId.InvalidElementId);
            }

            CompoundStructure cs = hostObjAttr.GetCompoundStructure();

            if (cs != null)
            {
                ElementId matId = cs.LayerCount > 0 ? cs.GetMaterialId(0) : ElementId.InvalidElementId;
                if (matId != ElementId.InvalidElementId)
                {
                    return(matId);
                }
                else
                {
                    return(CategoryUtil.GetBaseMaterialIdForElement(hostObject));
                };
            }

            return(ElementId.InvalidElementId);
        }
예제 #2
0
        public static List <Layer> GetLayers(Revit.Elements.WallType wallType)
        {
            Document document = DocumentManager.Instance.CurrentDBDocument;

            var wt = wallType.InternalElement as Autodesk.Revit.DB.WallType;
            CompoundStructure structure = wt.GetCompoundStructure();
            int layerCount     = structure.LayerCount;
            int strMaterialInd = structure.StructuralMaterialIndex;

            List <Layer> layers = new List <Layer>();

            for (int i = 0; i < layerCount; i++)
            {
                layers.Add(new Layer(structure.GetLayerFunction(i).ToString(),
                                     document.GetElement(structure.GetMaterialId(i)) as Autodesk.Revit.DB.Material,
                                     UnitUtils.ConvertFromInternalUnits(structure.GetLayerWidth(i), DisplayUnitType.DUT_MILLIMETERS),
                                     i == strMaterialInd,
                                     structure.IsCoreLayer(i)));
            }

            return(layers);
        }
예제 #3
0
        /// <summary>
        /// Gets the material ids of finish function of the host object.
        /// </summary>
        /// <param name="hostObject">The host object.</param>
        /// <returns>The material ids.</returns>
        public static ISet <ElementId> GetFinishMaterialIds(HostObject hostObject)
        {
            HashSet <ElementId> matIds = new HashSet <ElementId>();

            ElementId         typeElemId  = hostObject.GetTypeId();
            HostObjAttributes hostObjAttr = hostObject.Document.GetElement(typeElemId) as HostObjAttributes;

            if (hostObjAttr == null)
            {
                return(matIds);
            }

            ElementId         baseMatId = CategoryUtil.GetBaseMaterialIdForElement(hostObject);
            CompoundStructure cs        = hostObjAttr.GetCompoundStructure();

            if (cs != null)
            {
                for (int i = 0; i < cs.LayerCount; ++i)
                {
                    MaterialFunctionAssignment function = cs.GetLayerFunction(i);
                    if (function == MaterialFunctionAssignment.Finish1 || function == MaterialFunctionAssignment.Finish2)
                    {
                        ElementId matId = cs.GetMaterialId(i);
                        if (matId != ElementId.InvalidElementId)
                        {
                            matIds.Add(matId);
                        }
                        else if (baseMatId != ElementId.InvalidElementId)
                        {
                            matIds.Add(baseMatId);
                        }
                    }
                }
            }

            return(matIds);
        }
예제 #4
0
        /// <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);
            }
        }
        private void Stream(ArrayList data, CompoundStructure compStruct)
        {
            data.Add(new Snoop.Data.ClassSeparator(typeof(CompoundStructure)));

             data.Add(new Snoop.Data.Enumerable("Layers", compStruct.GetLayers()));

             int structuralMaterialIdx = compStruct.StructuralMaterialIndex;
             data.Add(new Snoop.Data.Int("Structural Material Index", structuralMaterialIdx));

             if (structuralMaterialIdx >= 0)
            data.Add(new Snoop.Data.ElementId("Structural Material (using StructuralMaterialIndex)", compStruct.GetMaterialId(structuralMaterialIdx), m_activeDoc));
             else
            data.Add(new Snoop.Data.ElementId("Structural Material (using StructuralMaterialIndex)", ElementId.InvalidElementId, m_activeDoc));

             data.Add(new Snoop.Data.Double("Width", compStruct.GetWidth()));
             data.Add(new Snoop.Data.Int("Variable Layer Index", compStruct.VariableLayerIndex));
             data.Add(new Snoop.Data.Bool("Is vertically compound", compStruct.IsVerticallyCompound));
             data.Add(new Snoop.Data.Bool("Is vertically homogeneous", compStruct.IsVerticallyHomogeneous()));
        }
예제 #6
0
        /// <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();

            MaterialIds = new List <Tuple <ElementId, string, double> >();
            IFCAnyHandle materialLayerSet = ExporterCacheManager.MaterialSetCache.FindLayerSet(typeElemId);

            // Roofs with no components are only allowed one material.  We will arbitrarily choose the thickest material.
            PrimaryMaterialHandle = ExporterCacheManager.MaterialSetCache.FindPrimaryMaterialHnd(typeElemId);
            if (IFCAnyHandleUtil.IsNullOrHasNoValue(materialLayerSet))
            {
                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.GetOverrideStringValue(material, "IfcMaterialLayer.Name", material.Name);
                        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 Tuple <ElementId, string, double>(baseMatId, layerName, matWidth));
                        }
                        // 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.GetOverrideStringValue(material, "IfcMaterialLayer.Name", material.Name);
                                    MaterialIds.Add(new Tuple <ElementId, string, double>(matid, layerName, matWidth));
                                }
                            }
                            else
                            {
                                MaterialIds.Add(new Tuple <ElementId, string, double>(baseMatId, null, matWidth));
                            }

                            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);
                            if (matId != ElementId.InvalidElementId)
                            {
                                Material material = m_Element.Document.GetElement(matId) as Material;
                                if (material != null)
                                {
                                    string layerName = NamingUtil.GetOverrideStringValue(material, "IfcMaterialLayer.Name", material.Name);
                                    MaterialIds.Add(new Tuple <ElementId, string, double>(matId, layerName, matWidth));
                                }
                            }
                            else
                            {
                                MaterialIds.Add(new Tuple <ElementId, string, double>(baseMatId, null, matWidth));
                            }
                            widths.Add(matWidth);
                            // save layer function into ProductWrapper,
                            // it's used while exporting "Function" of Pset_CoveringCommon
                            functions.Add(cs.GetLayerFunction(ii));
                        }
                    }

                    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.GetOverrideStringValue(material, "IfcMaterialLayer.Name", material.Name);
                                MaterialIds.Add(new Tuple <ElementId, string, double>(baseMatId, layerName, matWidth));
                            }
                        }
                        functions.Add(MaterialFunctionAssignment.None);
                    }
                }

                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.
                    if (widths[ii] < -MathUtil.Eps())
                    {
                        continue;
                    }

                    bool almostZeroWidth = MathUtil.IsAlmostZero(widths[ii]);
                    if (!ExporterCacheManager.ExportOptionsCache.ExportAs4 && almostZeroWidth)
                    {
                        continue;
                    }

                    if (almostZeroWidth)
                    {
                        widths[ii] = 0.0;
                    }

                    IFCAnyHandle materialHnd = CategoryUtil.GetOrCreateMaterialHandle(m_ExporterIFC, MaterialIds[ii].Item1);
                    if (PrimaryMaterialHandle == null || (widths[ii] > thickestLayer))
                    {
                        PrimaryMaterialHandle = materialHnd;
                        thickestLayer         = widths[ii];
                    }

                    widthIndices.Add(ii);
                    materialHnds.Add(materialHnd);

                    if ((m_ProductWrapper != null) && (functions[ii] == MaterialFunctionAssignment.Finish1 || functions[ii] == MaterialFunctionAssignment.Finish2))
                    {
                        m_ProductWrapper.AddFinishMaterial(materialHnd);
                    }
                }

                int numLayersToCreate = widthIndices.Count;
                if (numLayersToCreate == 0)
                {
                    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)
                {
                    string paramValue;
                    ParameterUtil.GetStringValueFromElementOrSymbol(m_Element, "IfcSingleMaterialOverride", out paramValue);
                    if (!string.IsNullOrEmpty(paramValue))
                    {
                        IFCAnyHandle singleMaterialOverrideHnd = IFCInstanceExporter.CreateMaterial(m_ExporterIFC.GetFile(), paramValue, null, null);
                        ExporterCacheManager.MaterialHandleCache.Register(MaterialIds[0].Item1, singleMaterialOverrideHnd);
                        MaterialLayerSetHandle = singleMaterialOverrideHnd;
                        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(widths[widthIndex]);

                    string layerName   = "Layer";
                    string description = null;
                    string category    = null;
                    int?   priority    = null;

                    IFCLogical?isVentilated = null;
                    int        isVentilatedValue;

                    Material material = document.GetElement(MaterialIds[ii].Item1) 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].Item2;
                            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);
                    }
                }

                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);
                        MaterialLayerSetHandle = IFCInstanceExporter.CreateMaterialConstituentSet(file, constituents, name: layerSetName, description: layerSetDesc);
                        foreach (Tuple <string, IFCAnyHandle> layerWidthQty in layerWidthQuantities)
                        {
                            LayerQuantityWidthHnd.Add(IFCInstanceExporter.CreatePhysicalComplexQuantity(file, layerWidthQty.Item1, null,
                                                                                                        new HashSet <IFCAnyHandle>()
                            {
                                layerWidthQty.Item2
                            }, "Layer", null, null));
                        }
                        // Finally create the total width as a quantity
                        LayerQuantityWidthHnd.Add(IFCInstanceExporter.CreateQuantityLength(file, "Width", null, null, totalWidth));
                    }
                    else
                    {
                        MaterialLayerSetHandle = IFCInstanceExporter.CreateMaterialLayerSet(file, layers, layerSetName, layerSetDesc);
                    }

                    ExporterCacheManager.MaterialSetCache.RegisterLayerSet(typeElemId, MaterialLayerSetHandle, this);
                }

                if (!IFCAnyHandleUtil.IsNullOrHasNoValue(PrimaryMaterialHandle))
                {
                    ExporterCacheManager.MaterialSetCache.RegisterPrimaryMaterialHnd(typeElemId, PrimaryMaterialHandle);
                }
            }
            else
            {
                MaterialLayerSetHandle = materialLayerSet;

                MaterialLayerSetInfo mlsInfo = ExporterCacheManager.MaterialSetCache.FindMaterialLayerSetInfo(typeElemId);
                if (mlsInfo != null)
                {
                    MaterialIds           = mlsInfo.MaterialIds;
                    PrimaryMaterialHandle = mlsInfo.PrimaryMaterialHandle;
                    LayerQuantityWidthHnd = mlsInfo.LayerQuantityWidthHnd;
                }
            }

            return;
        }
예제 #7
0
        Stream(ArrayList data, CompoundStructure compStruct)
        {
            data.Add(new Snoop.Data.ClassSeparator(typeof(CompoundStructure)));

            data.Add(new Snoop.Data.Enumerable("Layers", compStruct.GetLayers()));

            int structuralMaterialIdx = compStruct.StructuralMaterialIndex;

            data.Add(new Snoop.Data.Int("Structural Material Index", structuralMaterialIdx));

            if (structuralMaterialIdx >= 0)
            {
                data.Add(new Snoop.Data.ElementId("Structural Material (using StructuralMaterialIndex)", compStruct.GetMaterialId(structuralMaterialIdx), m_activeDoc));
            }
            else
            {
                data.Add(new Snoop.Data.ElementId("Structural Material (using StructuralMaterialIndex)", ElementId.InvalidElementId, m_activeDoc));
            }

            data.Add(new Snoop.Data.Double("Width", compStruct.GetWidth()));
            data.Add(new Snoop.Data.Int("Variable Layer Index", compStruct.VariableLayerIndex));
            data.Add(new Snoop.Data.Bool("Is vertically compound", compStruct.IsVerticallyCompound));
            data.Add(new Snoop.Data.Bool("Is vertically homogeneous", compStruct.IsVerticallyHomogeneous()));
        }
예제 #8
0
        /// <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
                            double matWidth = familySymbol.get_Parameter(BuiltInParameter.CURTAIN_WALL_SYSPANEL_THICKNESS)?.AsDouble() ??
                                              ParameterUtil.GetSpecialThicknessParameter(familySymbol);

                            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);

                            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?.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;
        }