齊保良,藺玉璞,楊秀芝,汪晴晴
(山東建筑大學(xué) 信息與電氣工程學(xué)院,濟南 250101)
近年來,建筑信息模型(Building Information Modeling,BIM)技術(shù)已廣泛應(yīng)用于建筑行業(yè),Revit 是BIM 技術(shù)常用的建模軟件之一[1].目前,鋼筋BIM 模型三維視圖中鋼筋型號、直徑等信息能夠采用引線方式標注[2,3],CAD 圖中的房間名稱等信息可以自動轉(zhuǎn)換到Revit 樓層平面圖中[4,5],但是,Revit 三維視圖無法顯示房間名稱及ID 信息,在仿真漫游或觀察剖面視圖時,需要由三維視圖切換到二維樓層平面圖查閱標注的房間名稱及ID,降低了工作效率.
本文旨在設(shè)計一種在Revit 三維視圖中自動標注房間名稱及ID 信息的中間件,減少仿真漫游或觀察剖面視圖時Revit 二維與三維視圖之間的多次切換,并自動準確定位房間位置,解決標注信息位置與模型重疊問題.
中間件,作為Revit 樓層平面圖與Revit 三維視圖之間的數(shù)據(jù)中轉(zhuǎn)站,在提取、存儲二維樓層平面數(shù)息標注到三維視圖模型房間方面做到了起承轉(zhuǎn)合的作用.
Visual Studio 是微軟基于.NET Framework 框架的一個集成開發(fā)環(huán)境.在本文中,Visual Studio 軟件作為Revit 二次開發(fā)的平臺.Revit 的應(yīng)用程序接口(API)能夠訪問Revit 模型的圖形數(shù)據(jù)、參數(shù)數(shù)據(jù).
基于Revit API 接口設(shè)計中間件有兩種方式:外部應(yīng)用函數(shù)(IExternalApplication ())和外部命令函數(shù)(IExternalCommand ()).Revit 開發(fā)平臺通過兩者后綴為“.addin”的文件識別和加載外部插件,其中IExternalApplication ()需要調(diào)用兩個接口命令函數(shù)(OnStartup ()和OnShutdown ())創(chuàng)建應(yīng)用程序.該工作方式在運行的Revit 開發(fā)平臺上即可進行編程和調(diào)試工作,調(diào)試完畢重新加載運行調(diào)試的程序?qū)崿F(xiàn)功能擴展,節(jié)省編程調(diào)試時間.而IExternalCommand ()函數(shù)在程序調(diào)試時,需要關(guān)閉Revit 軟件平臺,返回到外部命令函數(shù)調(diào)用Execute ()函數(shù)調(diào)試程序,由于反復(fù)關(guān)閉和啟動Revit 軟件平臺,會需要更多的調(diào)試時間.
本文選用IExternalApplication ()函數(shù)創(chuàng)建功能面板,通過加載Addin Manager 來識別外部工具.該方式利用Visual Studio 集成開發(fā)環(huán)境、C#編程語言,添加引用Revit API.dll 和Revit API UI.dll 接口,搭建Revit 軟件應(yīng)用平臺,通過IExternalApplication ()函數(shù)來讀取應(yīng)用插件.基于Revit 的中間件二次開發(fā)技術(shù)的外部應(yīng)用操作流程如圖1所示.
在Revit 軟件平臺上,鏈接CAD 圖紙,由二次開發(fā)的“CAD 文字轉(zhuǎn)化”插件自動識別鏈接圖紙的房間名稱及ID 文字信息,并標注于Revit 樓層平面房間[6].自動標注Revit 三維視圖房間信息的中間件在此基礎(chǔ)上進行設(shè)計.具體設(shè)計可以分為三部分:中間件樓層房間信息獲取方法、中間件數(shù)據(jù)存儲及中間件模型房間信息標注方法.
在以標準建筑規(guī)范為準的Revit 二維樓層平面中,各房間通過Revit 軟件“標記房間”功能標識房間,并且它也是由建筑墻體、門窗等構(gòu)件無縫連接組成的封閉輪廓.其中不同房間名稱可能相同但是其ID 信息和坐標定位不同.通過Revit API 獲取樓層房間信息需對建筑房間內(nèi)的構(gòu)件進行訪問、類別過濾以及坐標定位.
2.1.1 建筑構(gòu)件的訪問
在建筑設(shè)計建模時,類別(Category)是一組圖元,類名是該組圖元的名稱[6].根據(jù)構(gòu)件標識特征,Revit API 對不同構(gòu)件進行辨別和訪問.該方法訪問系統(tǒng)族實例僅需要判斷構(gòu)件的類名屬性即可,訪問可載入族實例需要共同判斷構(gòu)件的類名及類別.
由于門、窗、柱等構(gòu)件沒有專用的系統(tǒng)類來表示,都是FamilyInsurance 的載入族實例,無法通過類名辨別,故Revit 二次開發(fā)的中間件需要采用類別和類名判斷載入族實例的構(gòu)件.

圖1 基于Revit 的中間件二次開發(fā)技術(shù)的外部應(yīng)用流程圖
2.1.2 建筑構(gòu)件的類別過濾
Revit 開發(fā)平臺中所有的對象構(gòu)件遍歷都要使用過濾收集器(FilteredElementCollector)收集被過濾的對象,在過濾操作時結(jié)合多個過濾器共同使用,過濾后,過濾收集器獲得滿足條件的對象構(gòu)件集合[7,8].
Revit API 創(chuàng)建過濾收集器后,選擇其中的構(gòu)件過濾條件,過濾當前樓層平面圖中的構(gòu)件,指定視圖中的可見對象或集合,例如房間(Room)、墻體(Wall)、門(Door)等.以Room 類為例:
FilteredElementCollector roomFilter=new Filtered ElementCollector(doc);//創(chuàng)建過濾集合
ElementCategoryFilter orCategory=new Element CategoryFilter(BuiltInCategory.OST_rooms);//創(chuàng)建類別過濾條件
roomFilter.WherePasses(roomCategory);//這個返回的是房間類別下的所有Element,包括了文件中的房間實例(對應(yīng)type 為FamilyInstance),和用來創(chuàng)建房間實例的類型(type 對應(yīng)FamilySymbol)
ElementClassFilter roomType=new Element Class Filter(typeof(FamilyInstance));//創(chuàng)建一個type 過濾器
roomFilter.WherePasses(doorType);
2.1.3 樓層房間信息獲取
由于建筑模型內(nèi)部是由多個房間和公共區(qū)域組成,所以判斷房間是獲取信息的主要依據(jù),而樓層房間內(nèi)的建筑構(gòu)件應(yīng)該由統(tǒng)一坐標系進行定位.Revit 樓層平面圖中,房間名稱及ID 信息標注于封閉房間墻體輪廓內(nèi)部.
(1)坐標轉(zhuǎn)化
在Revit 樓層平面圖內(nèi),不同圖元構(gòu)件間的坐標基準值不同,圖元構(gòu)件通過圖元間的相對位置進行定位.因此,圖元構(gòu)件首要進行坐標轉(zhuǎn)換,轉(zhuǎn)化為統(tǒng)一的模型坐標系.
Revit 軟件提供了Transform 類來進行坐標轉(zhuǎn)換,開發(fā)人員可以給Transform 對象進行賦值構(gòu)造轉(zhuǎn)換矩陣,使用該轉(zhuǎn)換矩陣將給定的坐標點坐標轉(zhuǎn)成模型坐標系.首先,初始化Transform,然后設(shè)置其目標坐標系的三個方向向量BasisX,BasisY,BasisZ 的值,使用Of Point 進行點坐標轉(zhuǎn)換,用Of Vector 進行向量坐標轉(zhuǎn)換,把目標點或向量坐標轉(zhuǎn)換到模型坐標系的坐標.
Revit 開發(fā)平臺內(nèi)的GeometryInstance.Tr ansform函數(shù)訪問族定義到模型中的位置矩陣,使用Transform轉(zhuǎn)換矩陣計算出樓層平面圖中的圖元構(gòu)件門、窗等族實例中的所有點在模型坐標系的位置(從族實例中獲取其點、線、面的坐標也可以通過GeometryInstance對象的GeometryInstance.GetIns tanceGeomery()函數(shù)直接返回在模型坐標系下的坐標).
(2)坐標定位
Revit 圖元構(gòu)件的定位信息通過兩種方式來獲取:
1)使用Revit.Location 函數(shù)來獲取定位簡單族實例位置.包含兩類對象:
①基于點的族實例:例如柱子、門窗和家具等.基于點的族實例的Location 屬性返回Location Point IP 對象,通過IP Point 獲得插入點的位置坐標以及IP Rotation 獲得該點的旋轉(zhuǎn)角度,其值為弧度值,逆時針旋轉(zhuǎn)為正.
②基于線的族實例:例如梁、墻等.基于線的族實例的Location 屬性返回Location Curve Ic 對象,通過Ic Curve 可返回基線,從而獲得路徑的起始點和終止點的位置信息.
2)使用Element Geometry 函數(shù)來獲取復(fù)雜圖元的點、面、線空間定位.例如:樓梯、屋頂、斜墻.
(3)確定房間邊界
在Revit 樓層平面中,通過Revit API 獲取標識房間的參數(shù)及封閉房間邊界坐標.房間邊界可以為幾種圖元構(gòu)件:墻體、門、窗、柱等.
圖元構(gòu)件元素為房間邊界的條件:
1)對于模型曲線的元素,它的類別是BuiltInCategory.OST_AreaSeparationLines.
2)對于其他元素,比如墻、柱,它們的房間邊界(BuihInParameter.WALL_ATTR_ROOM_B OUNDING)參數(shù)必須設(shè)為True.
Revit API 獲取所有房間邊界信息可以用Room 里的
public IList
(
SpatialElementBoundaryOptions options
)
BoundarySegment 函數(shù)集合IList

圖2 房間邊界類圖
(4)獲取房間信息
樓層房間經(jīng)建筑構(gòu)件的訪問和過濾收集器過濾后,將指定的集合房間存入創(chuàng)建好的收集器中,接著,使用Transform 類轉(zhuǎn)化為統(tǒng)一的模型坐標系,使用Revit.Location 獲取建筑樓層房間邊界的坐標定位信息;再通過Revit API 的內(nèi)置參數(shù)BuiltInParameter.ELEM_ROOM_NAME 直接識別和提取房間名稱、ID 字符串,為下一步數(shù)據(jù)存儲做好準備.
利用各樓層房間邊界的區(qū)域坐標數(shù)據(jù)范圍來表示中間件獲取的樓層房間名稱及ID 信息.在Revit 樓層平面圖中,定義圖紙樓層房間的左下角為坐標系原點(0,0),分別利用直角坐標系表示各個封閉多邊形的4 個節(jié)點,而4 個節(jié)點分別做4 條直線X=Xi,X=Xj,Y=Yi,Y=Yj,該四條直線所圍成的封閉多邊形為房間邊界輪廓,利用Boundary Segment 函數(shù)來確定房間邊界,取該封閉多邊形區(qū)域的陰影部分任意一點表示該房間的名稱及ID 信息.如圖3所示.

圖3 封閉多邊形的定義信息圖
以某幼兒園施工圖的一層樓層平面為例(如圖4所示),取施工圖中某一特征點A(xi,yi),其中(x0≤xi≤x1,y0≤yi≤y1)內(nèi)的點代表活動室101;(x1≤xi≤x2,y1≤yi≤y2)內(nèi)的點代表辦公室103 以此類推.

圖4 以某幼兒園施工圖的一層樓層平面
數(shù)據(jù)庫作為Revit 樓層平面圖與Revit 三維視圖之間的數(shù)據(jù)中轉(zhuǎn)站,在數(shù)據(jù)儲存、數(shù)據(jù)調(diào)用方面起到重要作用.
工程技術(shù)人員在進行模型房間標注時,需要鼠標移動選擇待標注的模型房間位置發(fā)送到中間件,而中間件需要獲取該位置的空間坐標系數(shù)據(jù)信息,才可以進行下一步的運算.所以,數(shù)據(jù)表存放著Revit 樓層平面圖中的各樓層房間直角坐標系、樓層信息以及房間名稱及ID 信息.
本方案中BIM 數(shù)據(jù)庫(Epplus 庫)的構(gòu)件主要包含2 張數(shù)據(jù)表,分別為:1)房間名稱及ID 的數(shù)據(jù)表,保存了BIM 模型中房間名稱及ID 信息;2)房間邊界的數(shù)據(jù)表,保存了BIM 模型中房間輪廓的坐標數(shù)據(jù)信息.
為清楚每條記錄都能夠被唯一識別,便于和其相關(guān)的語句相映射,需要定義房間名稱及ID 來使數(shù)據(jù)庫中每條記錄可以被唯一識別,以便于在各個表之間建立主鍵和外鍵關(guān)系.表1所示為一個房間存儲信息數(shù)據(jù)表,以房間的名稱及ID 作為主鍵,其他的字段包括文件名名稱、圍成房間邊界的墻體ID 及門窗等,清晰地反映房間的坐標數(shù)據(jù)信息.

表1 房間名稱及ID 數(shù)據(jù)表
以上述幼兒園為例,其中一層活動室101,教室103,二層辦公室201 等樓層分布,如圖4所示.提取直線X、Y 坐標數(shù)據(jù)信息,經(jīng)過E p p l us 庫輸出到Excel 表格,其中,表格抬頭分為“樓層信息”、“房間邊界坐標數(shù)據(jù)”、“房間名稱”、“房間ID”,按組將坐標信息寫入表2某幼兒園生成中間件的Excel 文件.
在Revit 三維視圖下,結(jié)合Revit API 判斷待標注的模型房間空間坐標系的位置,匹配中間件內(nèi)存儲坐標數(shù)據(jù),并提取模型待標注信息,將需要標注的房間名稱及ID 信息加載到模型房間中,完成標注.

表2 某幼兒園生成中間件的Excel 文件
2.3.1 Revit 坐標數(shù)據(jù)匹配算法
在Revit 三維視圖中,獲取模型標注信息,匹配中間件內(nèi)坐標數(shù)據(jù)信息算法思路:確定需要標注的模型房間,取其模型房間內(nèi)任意一點A,獲取該點空間坐標系(xi,yi,zk),令zk代表樓層的高度,(xi,yj)代表樓層房間內(nèi)的位置,如圖5所示.

圖5 獲取空間坐標系
根據(jù)zk的大小,判斷其所屬樓層平面內(nèi)的樓層范圍,從而獲得樓層ID;再將A點在XY 平面內(nèi)分別作X 軸、Y 軸垂線,根據(jù)(xi,yj)能夠通過與中間件文件內(nèi)數(shù)據(jù)的匹配,準確判斷獲得樓層ID 的直角坐標系所屬范圍,從而獲得整個模型房間的名稱及ID.三維模型房間的數(shù)據(jù)信息匹配算法流程圖,如圖6所示.
具體的判斷方法:在空間坐標系中,令Z 軸代表樓層的高度,X、Y 軸代表樓層房間內(nèi)水平位置.以圖5的A點為例,根據(jù)zk的大小,判斷其樓層平面內(nèi)的樓層ID,假如 0≤zk≤1,則代表樓層平面的一層;1≤zk≤2,則代表二層.而A點的(xi,yj)坐標代表樓層內(nèi)的房間位置,判斷該點的(xi,yj)是匹配中間件存儲的直角坐標系數(shù)據(jù)組的范圍,根據(jù)表2生成的.xls 文件,假如x0≤xi≤x1,y0≤yj≤y1,0≤zk≤1,則確定該房間是活動室101;x1≤xi≤x2,y0≤yj≤y1,1≤zk≤2,則確定該房間是教室102,以此類推.

圖6 模型信息數(shù)據(jù)匹配算法流程圖
訪問中間件存儲數(shù)據(jù),需要C#語言在VS 中進行添加引用.dll 文件,以下為連接中間件的程序主要代碼:
string strConnect="Provider=Microsoft.Ace.OleDb.12.0;" + "data source=" + excelFilePath + ";Extended Properties='Excel 12.0;HDR=Yes;IMEX=1'";
2.3.2 Revit 三維視圖中模型信息提取標注
在Revit 三維視圖中,對中間件內(nèi)存儲的樓層平面內(nèi)坐標數(shù)據(jù)的訪問、提取,利用遍歷特征,獲取房間名稱和ID 的屬性信息.提取數(shù)據(jù)信息的具體流程如圖7所示.
在仿真漫游或是剖面視圖下,采取鼠標觸發(fā)事件技術(shù),顯示房間的名稱和ID 信息,利用提示節(jié)點(Tooltip)函數(shù)功能,提取中間件信息實現(xiàn)標注.當鼠標移動其模型房間區(qū)域內(nèi)任意一點時,模型房間信息將會通過提示節(jié)點出現(xiàn)在鼠標旁,適時顯示模型房間的信息;當鼠標移開之后,信息消失.具體實現(xiàn)顯示信息流程如圖8所示.

圖7 Revit 數(shù)據(jù)信息提取流程圖

圖8 模型房間顯示方式
經(jīng)過上述中間件房間數(shù)據(jù)信息的描述,自動標注Revit 三維房間信息中間件框架設(shè)計流程圖,如圖9所示.
具體總結(jié)為幾個步驟:
Step 1.在Revit 樓層平面圖中,通過Revit API 接口對建筑構(gòu)件訪問,創(chuàng)建過濾收集器、過濾條件,將房間Room 存入到收集器中.
Step 2.各樓層房間圖元構(gòu)件利用Transform 函數(shù)坐標轉(zhuǎn)化為統(tǒng)一的模型坐標系,RevitLocation 函數(shù)坐標定位獲取房間區(qū)域邊界輪廓的坐標數(shù)據(jù),利用Revit API 內(nèi)置參數(shù)BuiltInParameter.ELEM_ROOM_NAME獲取房間名稱及ID 字符串信息.
Step 3.結(jié)合SQL server,建立基于BIM 數(shù)據(jù)庫(Epplus 庫),并定義ID 使得數(shù)據(jù)庫中每條記錄可以被唯一識別,確立各個表之間主鍵和外鍵關(guān)系,接著,將Step 2 中提取的房間信息存儲到數(shù)據(jù)庫,并將數(shù)據(jù)庫存儲信息寫入Excel 文件.
Step 4.在Revit 三維視圖中,判斷待標注的模型房間空間坐標系的位置,再次借助Revit API 接口,提取空間位置坐標數(shù)據(jù).
Step 5.采用坐標數(shù)據(jù)匹配算法,將空間定位的位置坐標數(shù)據(jù)組與中間件存儲的直角坐標數(shù)據(jù)信息進行匹配,提取待標注數(shù)據(jù)信息.
Step 6.利用鼠標觸發(fā)事件,顯示三維視圖中模型房間名稱及ID 信息,完成標注.

圖9 自動標注Revit 三維房間信息中間件設(shè)計流程圖
根據(jù)分析以上所提出的三維視圖房間標注方法,采用面向?qū)ο蠹夹g(shù)的C#語言,使用Visual Studio 2013 進行代碼編寫,在Autodesk Revit 2016 中進行測試.其中在Revit 中,利用外部命令A(yù)ddin Manager 來加載運行編譯完成的中間件名稱“fangjian.dll”—點擊“fangjian.Command”—“Run”運行加載模型房間的標注.圖10為Revit 附加模塊生成的中間件.
本測試是以某幼兒園實際工程為案例,一樓三維剖面視圖上進行標注,其標注內(nèi)容為房間名稱及ID,完成效果如圖11所示.

圖10 在Revit 中運行的中間件

圖11 某幼兒園1 樓活動室三維剖面視圖模型房間標注
Revit 三維模型的標注,將房間的名稱及ID 添加到三維模型中,能夠讓工程技術(shù)人員清晰的看到房間的名稱和ID,相比較于之前需要查閱Revit 樓層平面上的標注來確定房間名稱及ID,節(jié)省了部分時間,提高了閱圖效率.
本文主要結(jié)合Revit 二次開發(fā)技術(shù),重點研究模型房間在三維視圖中自動標注房間名稱和ID 信息的方法,具體得到以下結(jié)論:
1)本文借助Revit API 接口,研究了Revit 三維模型視圖中自動標注樓層平面房間信息的方法,該方法能夠?qū)菍悠矫娣块g坐標信息提取并存儲到中間件中,而且調(diào)用中間件存儲信息自動匹配坐標數(shù)據(jù)對模型房間標注名稱和ID 信息.
2)以某幼兒園工程為例驗證程序的可行性及穩(wěn)定性.通過工程圖紙房間測試,能夠看到三維視圖中的房間名稱及ID 信息.給設(shè)計人員和審圖人員節(jié)省了部分時間,提高了工作效率.
3)本文研究的三維標注模型房間自動標注方法有待更多的工程實例測試,此外,由于BIM 模型本身的復(fù)雜性,更多的豐富信息標注待進一步研究,這也為Revit在三維模型標注方面或其他程序開發(fā)提供一些經(jīng)驗.