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