最近群里的朋友们这个问题问的比较多,有必要写一篇文章介绍利用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