1. 程式人生 > >Revit 二次開發獲取元素的材質和外觀資訊以及貼圖

Revit 二次開發獲取元素的材質和外觀資訊以及貼圖

最近群裡的朋友們這個問題問的比較多,有必要寫一篇文章介紹利用Revit 二次開發獲取元素的材質和貼圖的方法!

總體來說利用Revit API 獲取元素的材質和貼圖比較麻煩,而且有的材質還無法獲取。總結一下思路如下:

1.假設我們已經得到元素,利用Element.GetMaterialIds 方法可以獲得該元素所有材質的ElementId,注意這是一個集合!

2.將獲取到的ElementId轉化為Material物件。就能得到材質名,顏色,填充圖形等等資訊。

3.利用Material的AppearanceAssetId屬性得到AppearanceAssetId

4.通過3取得的AppearanceAssetId取得AppearanceAssetElement。

5.AppearanceAssetElement.GetRenderingAsset()獲得Asset。

這裡需要注意,如果您的材質是歐特克材質庫的材質,那麼恭喜你,這個函式取得的Asset長度為0.也就是說,毛也沒取到!怎麼處理後面再說。

6.解析第5步取得的Asset,Revit二次開發裡某個物件叫xxxSet,那麼這個物件一定是個集合。所以需要一個迴圈把集合中每一個物件都拉出來分析。

這個集合裡每一個物件都是一個AssetProperty。

7.AssetProperty 看見後面的Property就知道這是一個屬性的集合,你也需要把每一個屬性拉出來分析。

8.屬性型別包括APT_Integer,APT_Distance等等等等,你需要為每一種寫一套程式碼讀取它的屬性值

9.還有一種屬性型別叫APT_Reference,看見Reference頭暈不,這就說明這個屬性引用了其它屬性,碰上這種型別的,你還要做一個遞迴。

10.如果你找到了一個名字叫unifiedbitmap_Bitmap的屬性,那麼恭喜你,你找到了該元素的貼圖路徑。

11.下面回過頭看第5步,如果是AppearanceAssetElement.GetRenderingAsset()集合獲得空集合時。說明該材質使用了歐特克材質庫的材質。

那麼需要用Application.get_Assets獲得歐特克材質庫

寫了這麼多,直接上程式碼吧,不寫註釋是我的優良傳統,弄不明白看上面的說明吧。

程式碼中objBll.InsertMaterialMx都是資料庫操作,我把匯出材質資訊存入資料庫中。大家可以無視

 public void ReadAsset(Asset asset, string strMaterialId, StreamWriter objWriter)
        {
            // Get the asset name, type and library name.
            string name = asset.Name;

            // travel the asset properties in the asset.
            for (int idx = 0; idx < asset.Size; idx++)
            {
                AssetProperty prop = asset[idx];
                ReadAssetProperty(prop, strMaterialId, name, objWriter);
            }
        }



 public void ReadAssetProperty(AssetProperty prop, string strMaterialId, string strName, StreamWriter objWriter)
        {
            var objBll = new RevitMaterialExportBll();

            switch (prop.Type)
            {
                // Retrieve the value from simple type property is easy.
                // for example, retrieve bool property value.
                    case AssetPropertyType.APT_Integer:
                    var AssetPropertyInt = prop as AssetPropertyInteger;
                    objWriter.WriteLine(AssetPropertyInt.Name + "= " + AssetPropertyInt.Value.ToString());
                    if (!objBll.CheckMaterialMxExists(strMaterialId, AssetPropertyInt.Name))
                    {
                        objBll.InsertMaterialMx(strMaterialId, AssetPropertyInt.Name,GetDbData( AssetPropertyInt.Value), "APT_Integer");
                    }
                    break;

                case AssetPropertyType.APT_Distance:
                     var AssetPropertyDistance = prop as AssetPropertyDistance;
                     objWriter.WriteLine(AssetPropertyDistance.Name + "= " + AssetPropertyDistance.Value);
                     if (!objBll.CheckMaterialMxExists(strMaterialId, AssetPropertyDistance.Name))
                     {
                         objBll.InsertMaterialMx(strMaterialId, AssetPropertyDistance.Name, GetDbData(AssetPropertyDistance.Value), "AssetPropertyDistance");
                     }
                    break;

                case AssetPropertyType.APT_Double:
                    var AssetPropertyDouble = prop as AssetPropertyDouble;
                    objWriter.WriteLine(AssetPropertyDouble.Name + "= " + AssetPropertyDouble.Value.ToString());
                    if (!objBll.CheckMaterialMxExists(strMaterialId, AssetPropertyDouble.Name))
                    {
                        objBll.InsertMaterialMx(strMaterialId, AssetPropertyDouble.Name, GetDbData(AssetPropertyDouble.Value), "AssetPropertyDouble");
                    }
                    break;

                case AssetPropertyType.APT_DoubleArray2d:
                    var AssetPropertyDoubleArray2d = prop as AssetPropertyDoubleArray2d;
                    objWriter.WriteLine(AssetPropertyDoubleArray2d.Name + "= " + AssetPropertyDoubleArray2d.Value.ToString());
                    break;

                case AssetPropertyType.APT_DoubleArray4d:
                    var AssetPropertyDoubleArray4d = prop as AssetPropertyDoubleArray4d;
                    objWriter.WriteLine(AssetPropertyDoubleArray4d.Name + "= " + AssetPropertyDoubleArray4d.Value.ToString());
                    if (!objBll.CheckMaterialMxExists(strMaterialId, AssetPropertyDoubleArray4d.Name))
                    {
                        objBll.InsertMaterialMx(strMaterialId, AssetPropertyDoubleArray4d.Name, GetDbData(AssetPropertyDoubleArray4d.Value), "AssetPropertyDoubleArray4d");
                    }
                    break;

                case AssetPropertyType.APT_String:
                    AssetPropertyString val = prop as AssetPropertyString;
                    
                    objWriter.WriteLine(val.Name + "= " + val.Value);
                    if (!objBll.CheckMaterialMxExists(strMaterialId, val.Name))
                    {
                        objBll.InsertMaterialMx(strMaterialId, val.Name, GetDbData(val.Value), "APT_String");
                    }
                    break;
                case AssetPropertyType.APT_Boolean:
                    AssetPropertyBoolean boolProp = prop as AssetPropertyBoolean;
                    objWriter.WriteLine(boolProp.Name + "= " + boolProp.Value.ToString());
                    if (!objBll.CheckMaterialMxExists(strMaterialId, boolProp.Name))
                    {
                        objBll.InsertMaterialMx(strMaterialId, boolProp.Name, GetDbData(boolProp.Value), "APT_Boolean");
                    }
                    break;

                // When you retrieve the value from the data array property,
                // you may need to get which value the property stands for.
                // for example, the APT_Double44 may be a transform data.
                case AssetPropertyType.APT_Double44:
                    AssetPropertyDoubleArray4d transformProp = prop as AssetPropertyDoubleArray4d;
                    Autodesk.Revit.DB.DoubleArray tranformValue = transformProp.Value;
                    objWriter.WriteLine(transformProp.Name + "= " + transformProp.Value.ToString());
                    if (!objBll.CheckMaterialMxExists(strMaterialId, transformProp.Name))
                    {
                        objBll.InsertMaterialMx(strMaterialId, transformProp.Name, GetDbData(transformProp.Value), "APT_Double44");
                    }
                    break;

                // The APT_List contains a list of sub asset properties with same type.
                case AssetPropertyType.APT_List:
                    AssetPropertyList propList = prop as AssetPropertyList;
                    IList<AssetProperty> subProps = propList.GetValue();
                    if (subProps.Count == 0)
                        break;
                    switch (subProps[0].Type)
                    {
                        case AssetPropertyType.APT_Integer:
                            foreach (AssetProperty subProp in subProps)
                            {
                                AssetPropertyInteger intProp = subProp as AssetPropertyInteger;
                                int intValue = intProp.Value;
                                objWriter.WriteLine(intProp.Name + "= " + intProp.Value.ToString());
                            }
                            break;
                    }
                    break;

                case AssetPropertyType.APT_Asset:
                    Asset propAsset = prop as Asset;
                    ReadAsset(propAsset, strMaterialId, objWriter);
                    break;

                    case AssetPropertyType.APT_Reference:
                    
                    break;
                default:
                    objWriter.WriteLine("居然有啥都不是型別的" + prop.Type.ToString());
                    break;

            }

            // Get the connected properties.
            // please notice that the information of many texture stores here.
            if (prop.NumberOfConnectedProperties == 0)
                return;
            foreach (AssetProperty connectedProp in prop.GetAllConnectedProperties())
            {
                // Note: Usually, the connected property is an Asset.
                ReadAssetProperty(connectedProp, strMaterialId, strName, objWriter);
            }
        }

<pre name="code" class="html">        private void ExportMaterialInfo(ExternalCommandData commandData)
        {
            var objDoc = commandData.Application.ActiveUIDocument.Document;
            var objApp = commandData.Application.Application;
            var collector = new FilteredElementCollector(objDoc);
            var objBll = new RevitMaterialExportBll();
            var classfilter = new ElementClassFilter(typeof(Material));
            collector.WherePasses(classfilter);
            var beamList = collector.ToElements();

            // 讀取revit標準材質庫
            var objlibraryAsset = objApp.get_Assets(AssetType.Appearance);

            //寫入臨時檔案
            using (var objWriter = new StreamWriter(@"D:\aaa.txt"))
            {

                foreach (var objLoopItem in beamList)
                {
                    var objMaterial = objLoopItem as Material;
                    if (objMaterial != null)
                    {

                        var assetElementId = objMaterial.AppearanceAssetId;
                        var objMainColor = objMaterial.Color.Red + "," + objMaterial.Color.Green + "," +
                                           objMaterial.Color.Blue;
                        var objMaterialId = GetDbData(objMaterial.Id);

                        // 檢查資料庫中此材質是否存在
                        if (!objBll.CheckMaterialExists(objMaterialId))
                        {
                            objBll.InsertMaterial(objMaterialId, GetDbData(assetElementId), objMaterial.Name, objMainColor);
                        }

                        if (assetElementId != ElementId.InvalidElementId)
                        {
                            var objassetElement = objDoc.GetElement(assetElementId) as AppearanceAssetElement;
                            if (objassetElement != null)
                            {
                                var currentAsset = objassetElement.GetRenderingAsset();

                                // 檢索不到材質外觀時,為歐特克材質庫材質
                                if (currentAsset.Size == 0)
                                {
                                    foreach (Asset objCurrentAsset in objlibraryAsset)
                                    {
                                        if (objCurrentAsset.Name == currentAsset.Name &&
                                            objCurrentAsset.LibraryName == currentAsset.LibraryName)
                                        {
                                            ReadAsset(objCurrentAsset, objMaterial.Id.ToString(), objWriter);
                                        }
                                    }
                                }
                                else
                                {
                                    ReadAssetProperty(currentAsset, objMaterial.Id.ToString(), objMaterial.Name,
                                        objWriter);
                                }
                            }

                        }

                    }
                }
                objWriter.Close();
            }
        }

最後附上一張儲存進資料庫系統的資料圖片




大連智慧築城科技發展有限公司    貝克漢鴨   QQ:2443485