1.設(shè)計思路

創(chuàng)建樓板面層.png
其中,在運行前設(shè)置的時候需要創(chuàng)建ui界面,其他處理包含將樓板標記信息同步為樓板所在房間編號和將樓板面層信息同步為樓板面層名稱。
2.后臺處理
通過過濾器獲得所有的房間
public List<Element> getRoomList(Document doc) //獲取所有房間
{
FilteredElementCollector RoomCollector = new FilteredElementCollector(doc);
RoomCollector.OfCategory(BuiltInCategory.OST_Rooms).OfClass(typeof(SpatialElement));//SpatialElement空間元素
List<Element> RoomList = RoomCollector.ToList();
return RoomList;
}
通過過濾器獲得所有樓板的集合
private List<Element> getFloorList(Document doc) //獲取樓板集合
{
FilteredElementCollector FloorCollector = new FilteredElementCollector(doc);
FloorCollector.OfCategory(BuiltInCategory.OST_Floors).OfClass(typeof(FloorType));//SpatialElement空間元素
List<Element> FloorList = FloorCollector.ToList();
return FloorList;
}
通過比較房間中所有輪廓的拉伸體的體積,獲取房間的最大輪廓
private List<CurveArray> RoomBoundaryList(List<Element> roomList) //獲取房間輪廓
{
List<CurveArray> CurveArrayList = new List<CurveArray>();
foreach(Element element in roomList)
{
Room room = element as Room;
SpatialElementBoundaryOptions seBoundaryOption = new SpatialElementBoundaryOptions();
CurveArray ca = new CurveArray();
IList<IList<BoundarySegment>> roomBoundaryListList = room.GetBoundarySegments(seBoundaryOption);
List<CurveLoop> curveLoopList = new List<CurveLoop>();
//獲取房間的所有邊界
if(roomBoundaryListList!=null)
{
foreach(IList<BoundarySegment> roomBoundaryList in roomBoundaryListList)
{
CurveLoop curveLoop = new CurveLoop();
foreach(BoundarySegment roomBoundary in roomBoundaryList)
{
curveLoop.Append(roomBoundary.GetCurve());
}
curveLoopList.Add(curveLoop);
}
}
//獲取房間邊界拉伸體的體積
List<double> volumn = new List<double>();
try
{
foreach(CurveLoop curveLoop in curveLoopList)
{
IList<CurveLoop> cList = new List<CurveLoop>();
cList.Add(curveLoop);
Solid solid = GeometryCreationUtilities.CreateExtrusionGeometry(cList, XYZ.BasisZ, 1);
volumn.Add(solid.Volume);
}
}
catch
{
continue;
}
//通過房間邊界拉伸體的體積找出最大輪廓
CurveLoop LargeLoop = curveLoopList.ElementAt(volumn.IndexOf(volumn.Max()));
foreach(Curve curve in LargeLoop)
{
ca.Append(curve);
}
CurveArrayList.Add(ca);
}
return CurveArrayList;
}
繪制樓層面板
private bool CreateSurface(Document doc,FloorType floorType,List<CurveArray> roomBoundaryList)
{
using (Transaction Trans = new Transaction(doc, "生成樓層面板"))
{
Trans.Start();
foreach(CurveArray ca in roomBoundaryList)
{
Floor floor = doc.Create.NewFloor(ca, false);
}
Trans.Commit();
}
return true;
}
其中,過濾房間和過濾樓板的函數(shù)可以合并為一個,根據(jù)傳入函數(shù)的不同來過濾。
3.界面設(shè)計

ui
采用winform設(shè)計,工具箱直接拖控件,很神奇的是在vs里面看不到標題,于是手動在代碼里面添加了this.Text = "創(chuàng)建樓板面層",然后發(fā)現(xiàn)vs還是看不到,但是revit里面卻顯示有,而且生平第一次用中文來當變量名,震驚了。
界面代碼:
using System;
using System.Collections.Generic;
using System.Windows.Forms;
using Autodesk.Revit.DB;
namespace 創(chuàng)建樓板面層
{
public partial class setUi : System.Windows.Forms.Form
{
//聲明一個List對象rooms,通過rooms來找出屬性值
List<Element> rooms = null;
//構(gòu)造函數(shù),傳入房間集合,房間集合擁有的所有屬性名稱以及樓板類型
public setUi(List<Element> room, List<string> roomParametersNames, List<string> floorTypeNames)
{
InitializeComponent();
roomParametersNames.Add("無");
屬性名稱.DataSource = roomParametersNames;
類型名稱.DataSource = floorTypeNames;
rooms = room;
}
private void setUi_Load(object sender, EventArgs e)
{
this.Text = "創(chuàng)建樓板面層"; //設(shè)置窗口標題
//禁用放大和縮小按鈕
this.MaximizeBox = false;
this.MinimizeBox = false;
//設(shè)置combox的默認值
屬性名稱.SelectedIndex = 1;
屬性值.SelectedIndex = 0;
類型名稱.SelectedIndex = 0;
}
//找出屬性值的集合,傳入combox
private void 屬性名稱_SelectedIndexChanged(object sender, EventArgs e)
{
if (屬性名稱.SelectedItem != null)
{
string parameterName = 屬性名稱.SelectedItem.ToString();
List<string> parameterValuelist = new List<string>();
parameterValuelist.Add("無");
foreach (Element el in rooms)
{
屬性值.DataSource = null;
IList<Parameter> roomsPa = el.GetParameters(parameterName);
foreach (Parameter pa in roomsPa)
{
if (pa.HasValue)
{
if (pa.StorageType != StorageType.String)
{
if (!parameterValuelist.Contains(pa.AsValueString()))
{
parameterValuelist.Add(pa.AsValueString());
}
}
else
{
if (!parameterValuelist.Contains(pa.AsString()))
{
parameterValuelist.Add(pa.AsString());
}
}
}
}
}
屬性值.DataSource = parameterValuelist;
}
}
private void commitButton_Click(object sender, EventArgs e)
{
if (屬性名稱.SelectedItem != null &&屬性值.SelectedItem != null && 類型名稱.SelectedItem != null)
{
this.DialogResult = DialogResult.OK;
this.Close();
}
}
}
}
;
4.后臺代碼的再處理
對后臺代碼再處理,將ui返回的值傳到后臺,并根據(jù)條件創(chuàng)建樓板。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Autodesk.Revit.UI;
using Autodesk.Revit.DB;
using Autodesk.Revit.ApplicationServices;
using Autodesk.Revit.Attributes;
using Autodesk.Revit.DB.Architecture;
using System.Windows.Forms;
namespace 創(chuàng)建樓板面層
{
[Transaction(TransactionMode.Manual)]
public class CreateFloorSurface : IExternalCommand
{
public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
{
UIDocument uidoc = commandData.Application.ActiveUIDocument;
Document doc = uidoc.Document;
//過濾房間
List<Element> roomList = getRoomList(doc);
if(!(roomList.Count>0))
{
message = "模型中沒有繪制房間!";
return Result.Failed;
}
//過濾所有樓板
List<Element> floorList = getFloorList(doc);
if (!(floorList.Count > 0))
{
message = "模型中沒有繪制樓板!";
return Result.Failed;
}
//彈出對話框,選擇過濾條件和樓板類型
List<string> createSetting = ShowDialog(roomList, floorList);
if(!(createSetting.Count>0))
{
return Result.Cancelled;
}
//獲取房間輪廓
List<Element> roomsList = new List<Element>();
List<CurveArray> CuveArrayList = RoomBoundaryList(roomList,createSetting,out roomsList);
if (!(CuveArrayList.Count > 0))
{
message = "模型中的房間沒有輪廓!";
return Result.Failed;
}
//繪制樓層面板
FloorType ft = floorList.Where(x => x.Name == createSetting[2]).First() as FloorType;
bool result = CreateSurface(doc, ft, CuveArrayList,roomsList);
if (!result)
{
message = "樓層繪制失??!";
return Result.Failed;
}
return Result.Succeeded;
}
public List<Element> getRoomList(Document doc) //獲取所有房間
{
FilteredElementCollector RoomCollector = new FilteredElementCollector(doc);
RoomCollector.OfCategory(BuiltInCategory.OST_Rooms).OfClass(typeof(SpatialElement));//SpatialElement空間元素
List<Element> RoomList = RoomCollector.ToList();
return RoomList;
}
private List<Element> getFloorList(Document doc) //獲取樓板集合
{
FilteredElementCollector FloorCollector = new FilteredElementCollector(doc);
FloorCollector.OfCategory(BuiltInCategory.OST_Floors).OfClass(typeof(FloorType));
List<Element> FloorList = FloorCollector.ToList();
return FloorList;
}
private List<CurveArray> RoomBoundaryList(List<Element> roomList,List<string> createSetting,out List<Element> roomToCreate) //獲取房間輪廓
{
//通過傳入的creatSetting獲取指定房間
List<Element> roomsList = new List<Element>();
string paraName = createSetting[0];
string paraValue = createSetting[1];
foreach(Element ele in roomList)
{
ParameterMap paraMap = ele.ParametersMap;
foreach(Parameter para in paraMap)
{
if(para.Definition.Name==paraName)
{
if(para.HasValue)
{
string value;
if (para.StorageType == StorageType.String)
value = para.AsString();
else
value = para.AsString();
if (value == paraValue)
roomsList.Add(ele);
}
}
}
}
List<CurveArray> CurveArrayList = new List<CurveArray>();
roomToCreate = new List<Element>();
foreach(Element element in roomsList)
{
Room room = element as Room;
SpatialElementBoundaryOptions seBoundaryOption = new SpatialElementBoundaryOptions();
CurveArray ca = new CurveArray();
IList<IList<BoundarySegment>> roomBoundaryListList = room.GetBoundarySegments(seBoundaryOption);
List<CurveLoop> curveLoopList = new List<CurveLoop>();
//獲取房間的所有邊界
if(roomBoundaryListList!=null)
{
foreach(IList<BoundarySegment> roomBoundaryList in roomBoundaryListList)
{
CurveLoop curveLoop = new CurveLoop();
foreach(BoundarySegment roomBoundary in roomBoundaryList)
{
curveLoop.Append(roomBoundary.GetCurve());
}
curveLoopList.Add(curveLoop);
}
}
if (curveLoopList.Count == 0)
continue;
//獲取房間邊界拉伸體的體積
List<double> volumn = new List<double>();
try
{
foreach(CurveLoop curveLoop in curveLoopList)
{
IList<CurveLoop> cList = new List<CurveLoop>();
cList.Add(curveLoop);
Solid solid = GeometryCreationUtilities.CreateExtrusionGeometry(cList, XYZ.BasisZ, 1);
volumn.Add(solid.Volume);
}
}
catch
{
continue;
}
//通過房間邊界拉伸體的體積找出最大輪廓
CurveLoop LargeLoop = curveLoopList.ElementAt(volumn.IndexOf(volumn.Max()));
foreach(Curve curve in LargeLoop)
{
ca.Append(curve);
}
CurveArrayList.Add(ca);
roomToCreate.Add(element);
}
return CurveArrayList;
}
//創(chuàng)建樓板并同步房間和樓板類型
private bool CreateSurface(Document doc,FloorType floorType,List<CurveArray> roomBoundaryList,List<Element> roomsList)
{
double thick = floorType.get_Parameter(BuiltInParameter.FLOOR_ATTR_DEFAULT_THICKNESS_PARAM).AsDouble();
using (Transaction Trans = new Transaction(doc, "生成樓層面板"))
{
Trans.Start();
for(int i=0;i<roomBoundaryList.Count;i++)
{
Floor floor = doc.Create.NewFloor(roomBoundaryList[i],floorType,doc.GetElement(roomsList[i].LevelId)as Level , false);
floor.get_Parameter(BuiltInParameter.FLOOR_HEIGHTABOVELEVEL_PARAM).Set(thick); //更改偏移量
floor.get_Parameter(BuiltInParameter.ALL_MODEL_MARK).Set(roomsList[i].get_Parameter(BuiltInParameter.ROOM_NUMBER).AsString()); //同步房間信息
roomsList[i].get_Parameter(BuiltInParameter.ROOM_FINISH_FLOOR).Set(floorType.Name);
}
Trans.Commit();
}
return true;
}
//創(chuàng)建界面對象,并返回value,其中value包含combox選中的三個值
private List<string> ShowDialog(List<Element> roomList,List<Element> floorList)
{
//獲取房間編號,房間屬性名稱以及樓板類型
List<string> value = new List<string>(); //保存ui返還的值
List<Element> room = new List<Element>();
List<string> roomParametersNames = new List<string>();
List<string> floorTypeNames = new List<string>();
//找出屬性名稱,屬性值,以及樓板類型,并傳入給setUi的構(gòu)造函數(shù)
foreach (Element rm in roomList)
{
room.Add(rm);
}
ParameterMap pm = room[0].ParametersMap;
foreach (Parameter pa in pm)
{
if (!roomParametersNames.Contains(pa.Definition.Name))
{
roomParametersNames.Add(pa.Definition.Name);
}
}
foreach (Element el in floorList)
{
floorTypeNames.Add(el.Name);
}
setUi ui = new setUi(room, roomParametersNames, floorTypeNames);
if(ui.ShowDialog() == DialogResult.OK)
{
value.Add(ui.屬性名稱.SelectedItem.ToString());
value.Add(ui.屬性值.SelectedItem.ToString());
value.Add(ui.類型名稱.SelectedItem.ToString());
return value;
}
return null;
}
}
}
5.前方高能
神奇的是,ui設(shè)計器會出問題???不是很懂問題出在哪里,但是點擊“忽略并繼續(xù)”后,可以成功生成,而且運行也沒問題,哪位大佬路過看到了望告知。

這是高能