在項目中需要讀取rvt文件,但是因為該格式為非公開格式,其數據需要revit的支持,但批量讀取不可能一個一個用revit軟件去打開。不過該方法還是需要revit的依賴,速度比開軟件快了知道多少
1.1. 新建一個控制台項目
1.2. 添加Revit API引用
我們找到revit安裝目錄下的這兩個DLL添加到項目引用中
- RevitNET.dll
- RevitAPI.dll
修改屬性:復制本地:FALSE
1.3. 為MAIN函數添加STAThread特性
[STAThread]//一定要有
static void Main(string[] args)
{
}
如果未添加則報錯:
異常:SEHException: 外部組件發生異常。
1.4. 修改控制台項目為64位
由於revit為64位程序,所以我們的控制台程序一定要為64位才可正常使用。
1.5. 添加封裝好的revitContext類
可以直接使用,可以根據自己需要去修改,其中的Application就是revit主要的
public class RevitContext
{
#region private fields
Product _revitProduct;
private static bool isLoadEnv = false;//是否已添加過環境變量
#endregion
#region public fields
/// <summary>
/// revit程序目錄
/// </summary>
public static string RevitPath;
#endregion
#region event
public event EventHandler<Product> InitRevitFinished;
#endregion
#region public properties
/// <summary>
/// 打開REVIT文件時的設置
/// </summary>
public OpenOptions OpenOptions { get; set; }
/// <summary>
/// Revit Application
/// </summary>
public Autodesk.Revit.ApplicationServices.Application Application => this._revitProduct?.Application;
#endregion
#region constructors
/// <summary>
///
/// </summary>
/// <param name="revitPath">revit安裝目錄</param>
public RevitContext(string revitPath)
{
RevitPath = revitPath;
AddEnv();
}
/// <summary>
/// 使用此構造方法前需要調用 RevitContext.AddEnv();
/// </summary>
public RevitContext()
{
}
#endregion
#region public methods
public void InitRevit()
{
this.OpenOptions = new OpenOptions
{
Audit = true,
AllowOpeningLocalByWrongUser = false,
DetachFromCentralOption = DetachFromCentralOption.DetachAndDiscardWorksets //從中心模型分離
};
_revitProduct = Product.GetInstalledProduct();
var clientApplicationId = new ClientApplicationId(Guid.NewGuid(), "RevitContext", "BIM");
_revitProduct.SetPreferredLanguage(Autodesk.Revit.ApplicationServices.LanguageType.Chinese_Simplified);
_revitProduct.Init(clientApplicationId, "I am authorized by Autodesk to use this UI-less functionality.");
OnInitRevitFinished();
}
public Document OpenFile(string filename, OpenOptions options = null)
{
if (options == null)
{
options = this.OpenOptions;
}
ModelPath model = new FilePath(filename);
return this._revitProduct.Application.OpenDocumentFile(model, options);
}
/// <summary>
/// 獲取默認三維視圖
/// </summary>
/// <param name="document">文檔</param>
/// <returns></returns>
public View3D GetView3D(Document document)
{
if (document.ActiveView is View3D view3D && !view3D.IsPerspective && view3D.CanBePrinted)
{
return view3D;
}
FilteredElementCollector filter=new FilteredElementCollector(document);
return (View3D) filter.OfClass(typeof(View3D)).FirstElement();
}
/// <summary>
/// 獲取指定三維視圖
/// </summary>
/// <param name="document">文檔</param>
/// <param name="viewName">指定視圖名稱</param>
/// <returns></returns>
public View3D GetView3D(Document document,string viewName)
{
FilteredElementCollector filter = new FilteredElementCollector(document);
return (View3D)filter.OfClass(typeof(View3D)).FirstOrDefault(x => x.Name==viewName);
}
public IList<Element> GetElementsWithView(View3D view)
{
FilteredElementCollector collector=new FilteredElementCollector(view.Document,view.Id);
return collector.ToElements();
}
#endregion
#region public static methods
/// <summary>
/// 添加revit安裝路徑到環境變量以便加載相應的DLL
/// </summary>
/// <param name="revitPath">添加revit安裝路徑</param>
public static void AddEnv(string revitPath=null)
{
if (isLoadEnv)
{
return;
}
if (revitPath!=null)
{
RevitPath = revitPath;
}
AddEnvironmentPaths(RevitPath);
AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve;
}
#endregion
#region private static methods
/// <summary>
/// 添加環境變量
/// </summary>
/// <param name="paths">revit安裝路徑</param>
static void AddEnvironmentPaths(params string[] paths)
{
string[] first = {
Environment.GetEnvironmentVariable("PATH") ?? string.Empty
};
string value = string.Join(Path.PathSeparator.ToString(), first.Concat(paths));
Environment.SetEnvironmentVariable("PATH", value);
}
/// <summary>
/// 動態加載revit相關的dll
/// </summary>
/// <param name="sender"></param>
/// <param name="args"></param>
/// <returns></returns>
static Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
{
var assemblyName = new AssemblyName(args.Name);
var text = $"{Path.Combine(RevitPath, assemblyName.Name)}.dll";
Assembly result;
if (File.Exists(text))
{
Console.WriteLine($"Load Revit Dll Path:{text}");
result = Assembly.LoadFrom(text);
}
else
{
result = null;
}
return result;
}
#endregion
#region private methods
private void OnInitRevitFinished()
{
this.InitRevitFinished?.Invoke(this, this._revitProduct);
}
#endregion
}
1.6. 使用並測試
class Program
{
static RevitContext revit;
static Program()
{
RevitContext.AddEnv(@"D:\Program Files\Autodesk\Navisworks Manage 2020\Loaders\Rx\");
}
[STAThread]//一定要有
static void Main(string[] args)
{
revit = new RevitContext();
revit.InitRevitFinished += InitRevitFinished;
revit.InitRevit();
Console.ReadKey();
}
private static void InitRevitFinished(object sender, Product revitProduct)
{
Console.WriteLine("當前使用Revit版本為:" + revitProduct.Application.VersionName);
Document document = revit.OpenFile(@"E:\test\2019\經典小文件\2020.rvt");
View3D view = revit.GetView3D(document);
if (view!=null)
{
Console.WriteLine(view.Name);
var elements =revit.GetElementsWithView(view);
foreach (var element in elements)
{
Console.WriteLine(element.Name);
}
}
}
}
完成!
1.7. 留下的坑:
- 如何在不指定revit路徑的情況下加載(動態獲取revit安裝路徑)
- 根據revit文件版本加載相應的revit路徑
- 一個程序動態支持多版本revit
以上問題本人已有相應的方法。