Revit二次開發——匯出OBJ格式外掛
阿新 • • 發佈:2018-12-25
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格式外掛
- 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;
}
}
}
- 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