Revit二次開發之隱藏API 不直接打開revit讀取rvt文件

在項目中須要讀取rvt文件,可是由於該格式爲非公開格式,其數據須要revit的支持,但批量讀取不可能一個一個用revit軟件去打開。不過該方法仍是須要revit的依賴,速度比開軟件快了知道多少git

1.1. 新建一個控制檯項目

1.2. 添加Revit API引用

咱們找到revit安裝目錄下的這兩個DLL添加到項目引用中github

  • RevitNET.dll
  • RevitAPI.dll

修改屬性:複製本地:FALSEc#

1.3. 爲MAIN函數添加STAThread特性

[STAThread]//必定要有
        static void Main(string[] args)
        {
        }

若是未添加則報錯:api

異常:SEHException: 外部組件發生異常。less

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

        }
    }

完成!ui

1.7. 留下的坑:

  • 如何在不指定revit路徑的狀況下加載(動態獲取revit安裝路徑)
  • 根據revit文件版本加載相應的revit路徑
  • 一個程序動態支持多版本revit

以上問題本人已有相應的方法。this

源碼code

相關文章
相關標籤/搜索