1. 程式人生 > >Revit二次開發——匯出OBJ格式外掛

Revit二次開發——匯出OBJ格式外掛

Revit二次開發——匯出OBJ格式外掛

1、OBJ格式

關鍵字 備註
g
v 頂點
f

例子:
建立 Cube.txt 新增內容:

g Cube
v -1 -1 -1
v -1 1 -1
v 1 -1 -1
v 1 1 -1
v -1 -1 1
v -1 1 1
v 1 -1 1
v 1 1 1
f 1 2 3
f 2 3 4
f 5 6 7
f 6 7 8
f 1 2 5
f 2 5 6
f 3 4 7
f 4 7 8
f 2 4 6
f 4 6 8
f 1 3 5
f 3 5 7

Cube.txt 字尾名改成 .obj 後使用 畫圖 3D 軟體( Win10 版的畫圖,可在 Microsoft Store 下載)即可開啟檢視模型
在這裡插入圖片描述
2、Revit匯出OBJ格式外掛

  1. Execute函式
using System;
using Autodesk.Revit.Attributes;
using Autodesk.Revit.DB;
using Autodesk.Revit.UI;
using System.Collections.Generic;
using ExportOBJ.Utils;
using System.Windows.Forms;
using System.Linq; using System.IO; namespace ExportOBJ.Executes { [Transaction(TransactionMode.Manual)] [Regeneration(RegenerationOption.Manual)] [Journaling(JournalingMode.NoCommandData)] class ExportOBJExecute : IExternalCommand { //委託 private delegate void secondHandler
(); public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements) { try { Autodesk.Revit.ApplicationServices.Application revitApp = commandData.Application.Application; UIDocument uiDocument = commandData.Application.ActiveUIDocument; Document document = uiDocument.Document; //獲取所有構件 List<Element> elementList = ExportOBJUtil.GetElements(document).ToList(); //把所有構件根據不同樓層分類 Dictionary<string, List<Element>> floorTextDict = ExportOBJUtil.SortElementsByFloor(elementList); //專案名 string fileName = ExportOBJUtil.GetFileName(document); //根目錄 string rootPath = $@"C:\Users\ly\Desktop"; //建立資料夾 ExportOBJUtil.CreateFolder(rootPath, fileName); //顯示進度條 ProgressForm progressForm = new ProgressForm(); progressForm.Show(); //樓層百分比分子 double floorNumerator = 0; //樓層百分比分母 double floorDenominator = floorTextDict.Count; // Thread thread = new Thread(delegate () //{ //遍歷字典,key(string)樓層號,value(List<Element>)樓層包含的構件 foreach (var item in floorTextDict) { //顯示推送進度 progressForm.Invoke(new secondHandler(delegate () { //更新樓層進度條 progressForm.floorText.Text = item.Key; floorNumerator++; int floorPercent = (int)Math.Floor(floorNumerator / floorDenominator * 100); progressForm.floorProgressBar.Value = floorPercent; progressForm.floorPercent.Text = floorPercent.ToString(); })); //設定obj檔案輸出路徑 string folderPath = $@"{rootPath}\{fileName}\{fileName} {item.Key}.obj"; if (File.Exists(folderPath)) { File.Delete(folderPath); } //檔案流 FileStream fileStream = new FileStream(folderPath, FileMode.CreateNew); //寫入流 StreamWriter streamWriter = new StreamWriter(fileStream); //每個樓層當做一個組g string group = "g " + item.Key; //寫入組g streamWriter.WriteLine(group); //建立點索引vIndex int vIndex = 0; //構件百分比分子 double elementNumerator = 0; //構件百分比分母 double elementDenominator = item.Value.Count; //遍歷每個樓層的構件 foreach (Element element in item.Value) { //顯示推送進度 progressForm.Invoke(new secondHandler(delegate () { //更新構件進度條 progressForm.elementText.Text = element.Id.ToString(); elementNumerator++; int elementPercent = (int)Math.Floor(elementNumerator / elementDenominator * 100); progressForm.elementProgressBar.Value = elementPercent; progressForm.elementPercent.Text = elementPercent.ToString(); })); //遍歷這個構件的所有面 List<Face> faceList = ExportOBJUtil.GetFace(element, revitApp); //遍歷每個面 foreach (Face face in faceList) { //獲取單個面的所有網格 Mesh mesh = face.Triangulate(); if (null == mesh) { continue; } //遍歷每個三角網格 for (int i = 0; i < mesh.NumTriangles; i++) { //獲取面f string f = "f "; //獲取某個三角網格 MeshTriangle meshTriangle = mesh.get_Triangle(i); //獲取三角網格的三個點 for (int j = 0; j < 3; j++) { XYZ point = meshTriangle.get_Vertex(j); //獲取點v string v = $"v {-Math.Round(point.X, 2)} {Math.Round(point.Z, 2)} {Math.Round(point.Y, 2)}"; //寫入點v streamWriter.WriteLine(v); //點索引自增 vIndex++; //面f新增點索引 f += vIndex + " "; } //出去最後多出來的一個空格 f = f.Substring(0, f.Length - 1); //寫入面f streamWriter.WriteLine(f); } } //將快取推出,重新整理快取 streamWriter.Flush(); } } //progressForm.Invoke(new secondHandler(delegate () //{ //執行結束關閉進度條 progressForm.Close(); //})); //}); //thread.Start(); } catch (Exception ex) { MessageBox.Show(ex.ToString()); throw; } return Result.Succeeded; } } }
  1. ExportOBJUtil工具類
using Autodesk.Revit.DB;
using System.Collections.Generic;
using System.Linq;
using Autodesk.Revit.ApplicationServices;
using System.IO;

namespace ExportOBJ.Utils
{
    class ExportOBJUtil
    {
        /// <summary>
        /// 獲取所有構件
        /// </summary>
        /// <returns></returns>
        internal static IList<Element> GetElements(Document document)
        {
            FilteredElementCollector collector = new FilteredElementCollector(document);
            collector.WhereElementIsNotElementType();
            return collector.ToElements();
        }

        /// <summary>
        /// 根據樓層分類所有構件
        /// </summary>
        /// <param name="elementList"></param>
        /// <returns></returns>
        internal static Dictionary<string, List<Element>> SortElementsByFloor(List<Element> elementList)
        {
            Dictionary<string, List<Element>> floorTextDict = new Dictionary<string, List<Element>>();
            //遍歷所有構件
            foreach (Element element in elementList)
            {
                //獲取當前構件所在樓層
                string floorText = GetFloorText(element);
                //如果返回值為null進入下一個迴圈
                if (floorText == null)
                {
                    continue;
                }
                else//如果floorText不為空
                {
                    //判斷樓層字典中是否存在此樓層
                    if (floorTextDict.ContainsKey(floorText))
                    {
                        //如果存在則把該構件放在對應樓層
                        floorTextDict[floorText].Add(element);
                    }
                    else
                    {
                        //如果沒有建立新的樓層key
                        floorTextDict.Add(floorText, new List<Element>());
                        floorTextDict[floorText].Add(element);
                    }
                }
            }
            return floorTextDict;
        }

        /// <summary>
        /// 建立資料夾
        /// </summary>
        /// <param name="rootPath"></param>
        /// <param name="fileName"></param>
        internal static void CreateFolder(string rootPath, string fileName)
        {
            if (Directory.Exists(rootPath + "\\" + fileName))
            {
                return;
            }
            else
            {
                Directory.CreateDirectory(rootPath + "\\" + fileName);
            }
        }

        /// <summary>
        /// 獲取檔名
        /// </summary>
        /// <param name="document"></param>
        /// <returns></returns>
        internal static string GetFileName(Document document)
        {
            string fileName = "";

            string path = document.PathName;

            string[] pathArray = path.Split('\\');

            fileName = pathArray.Last().Substring(0, pathArray.Last().Length - 4);

            return fileName;
        }

        /// <summary>
        /// 獲取構件的面
        /// </summary>
        /// <param name="element"></param>
        /// <returns></returns>
        internal static List<Face> GetFace(Element element, Application revitApp)
        {
            List<Face> faceList = new List<Face>();

            GeometryElement geomElement = element.get_Geometry(GetGeometryOption(revitApp));
            foreach (GeometryObject geomObject in geomElement)
            {
                if (geomObject.GetType().Equals(typeof(Solid)))
                {
                    Solid solid = geomObject as Solid;
                    foreach (Face face in solid.Faces)
                    {
                        if (face.GetType().Equals(typeof(PlanarFace)))
                        {
                            faceList.Add(face);
                        }
                        else if (face.GetType().Equals(typeof(CylindricalFace)))
                        {
                            faceList.Add(face);
                        }
                    }
                }
                else if (geomObject.GetType().Equals(typeof(GeometryInstance)))
                {
                    GeometryInstance geometryInstance = geomObject as GeometryInstance;
                    foreach (GeometryObject geometryObject in geometryInstance.GetInstanceGeometry())
                    {
                        if (geometryObject.GetType().Equals(typeof(Solid)))
                        {
                            Solid solid = geometryObject as Solid;
                            foreach (Face face in solid.Faces)
                            {
                                if (face.GetType().Equals(typeof(PlanarFace)))
                                {
                                    faceList.Add(face);
                                }
                                else if (face.GetType().Equals(typeof(CylindricalFace)))
                                {
                                    faceList.Add(face);
                                }
                            }
                        }
                    }
                }
            }
            return faceList;
        }

        /// <summary>
        /// 建立一個Option
        /// </summary>
        /// <returns></returns>
        private static Options GetGeometryOption(Application app)
        {
            Options option = app.Create.NewGeometryOptions();
            option.ComputeReferences = true;      //開啟計算幾何引用 
            option.DetailLevel = ViewDetailLevel.Fine;      //檢視詳細程度為最好 
            return option;
        }

        /// <summary>
        /// 獲取構件所在的樓層
        /// </summary>
        /// <param name="element"></param>
        /// <returns></returns>
        private static string GetFloorText(Element element)
        {
            if (element.LookupParameter("樓層") == null)
            {
                return null;
            }
            else
            {
                return element.LookupParameter("樓層").AsString();
            }
        }
    }
}

最後貼上該專案的資源地址:https://download.csdn.net/download/qq_28907595/10830329