以前就已经对创建房间有过了解,只是点到为止没有进一步的深究下去,今天有点时间就整理一下思路,留着以后备用。其实创建完房间后,可以算房间面积,空间体积什么的,也可以获得房间的边界线去做一些工作,比如生成楼板,墙踢脚线,墙饰条等等,其实原理都一样就是利用房间的闭合曲线!
首先来一个批量创建房间的代码,这里就只写步骤了,不拷贝整个工程了
UIApplication uiApp = commandData.Application;
UIDocument uidoc = uiApp.ActiveUIDocument;
Document doc = uidoc.Document;
ViewPlan view = uidoc.ActiveView as ViewPlan;
Transaction ts = new Transaction(doc, "BIM");
ts.Start();
Level level = uidoc.ActiveView.GenLevel;
PlanTopology pt = doc.get_PlanTopology(level);
foreach (PlanCircuit pc in pt.Circuits)
{
if (!pc.IsRoomLocated)
{
Room newRoom = doc.Create.NewRoom(null, pc);
LinkElementId elemid = new LinkElementId(newRoom.Id);
Location location = newRoom.Location;
LocationPoint locationPoint = location as LocationPoint;
XYZ point3d = locationPoint.Point;
UV point2d = new UV(point3d.X, point3d.Y);
RoomTag roomTag = doc.Create.NewRoomTag(elemid, point2d, view.Id);
if (family != null)
{
try
{
//这里的symbol其实是自定义的一个房间标记族,可以自行导入,这里就不再介绍了
FamilySymbol symbol = family.Document.GetElement(family.GetFamilySymbolIds().First()) as FamilySymbol;
if (symbol != null)
{
roomTag.ChangeTypeId(symbol.Id);
}
}
catch { }
}
}
}
ts.Commit();
以上代码就是批量生成房间的代码段,接下来就是获得房间边界生成楼板,不过在此之前我们先看看每个房间边界的样子,我们可以根据Room.GetBoundarySegments()方法来获得 IList<>集合,根据这个集合去遍历所有的房间边界,在此之前我们还需要一个SpatialElementBoundaryOptions选项,它给我们提供了SpatialElementBoundaryLocation枚举类型,公有四个,分别是,Center,CoreBoundary,CoreCenter,finish,那么分别是什么意思呢,查阅一下RevitAPI帮助文档后得知:
1.Center,这里可以理解为墙的中心线
2.CoreBoundary,这里可以理解为墙的核心层边界线
3.CoreCenter,这里可以理解为墙的核心层中心线
4,.Finish.这里可以理解为墙的面层
上述翻译有可能不太准确,希望读者自行实验判断吧,接下来我们实测一下这四个选项,我的思路是根据房间的边界线生成详图线用以观察四个选项的区别,为了明显起见我想自定义一个线样式,宽度为1个单位,颜色为红色,主要代码如下:
////生成线样式
using (Transaction ts = new Transaction(doc, "LineStyle"))
{
ts.Start();
Category lineCategory = doc.Settings.Categories.get_Item(BuiltInCategory.OST_Lines);
Category newCategory = doc.Settings.Categories.NewSubcategory(lineCategory, "房间边界线");
Color newColor = new Color(255, 0, 0);
newCategory.LineColor = newColor;
newCategory.SetLineWeight(1, GraphicsStyleType.Projection);
ts.Commit();
}
生成之后的系统线样式下:
好了 那么接下来我们就可以过滤房间边界来看一看它们的样子:核心代码,记得开启事务
//这里拾取一个房间,为了简便没有加过滤器限制
Reference refer = uidoc.Selection.PickObject(ObjectType.Element, "");
Room room = doc.GetElement(refer) as Room;
SpatialElementBoundaryOptions opt = new SpatialElementBoundaryOptions();
opt.SpatialElementBoundaryLocation = SpatialElementBoundaryLocation.Center;
//声明的Curve集合是为创建楼板而服务的
CurveArray array = new CurveArray();
IList(IList(BoundarySegment)) loops = room.GetBoundarySegments(opt);
foreach (IList(BoundarySegment) loop in loops)
{
foreach (BoundarySegment seg in loop)
{
Curve curve = seg.GetCurve();
//创建详图线,设置它的线样式类型为我们刚才创建的
DetailCurve dc = doc.Create.NewDetailCurve(uidoc.ActiveView, curve);
if (BackLineStyle(doc) != null)
{
SetLineStyle(BackLineStyle(doc), dc);
}
array.Append(dc.GeometryCurve);
}
}
//两个相关的方法
//搜索目标线样式
private Category BackLineStyle(Document doc)
{
Category lineCategory = doc.Settings.Categories.get_Item(BuiltInCategory.OST_Lines);
CategoryNameMap map = lineCategory.SubCategories;
foreach (Category g in map)
{
if (g.Name == "房间边界线")
{
return g;
}
}
return null;
}
//设置线样式
private void SetLineStyle(Category cate, DetailCurve line)
{
ElementId Id = new ElementId(cate.Id.IntegerValue + 1);
foreach (Parameter p in line.Parameters)
{
if (p.Definition.Name == "线样式")
{
p.Set(Id);
break;
}
}
}
上述代买我们用的是Center选项,让我们来看看效果:
红色是房价你的边界线的路径,可以看得出与墙中心线重合,我使用的墙结构信息如下:
接上述代码获得房间边界,我们可以创建楼板,以下为核心代码:
//创建楼板,类型默认 标高默认
private void CreateFloor(Document doc,CurveArray array)
{
FloorType floorType= new FilteredElementCollector(doc).OfClass(typeof(FloorType)).FirstOrDefault() as FloorType;
Level level = new FilteredElementCollector(doc).OfClass(typeof(Level)).OrderBy(o => (o as Level).ProjectElevation).First() as Level;
Floor floor = doc.Create.NewFloor(array,floorType,level,false,XYZ.BasisZ);
}
生成楼板(其实根据闭合曲线能创建很多东西,也可以用其做族的放样,生成散水,踢脚线等,有时间我会写一个创建族的基本流程)之后的局部三维视图如下:
/////////////////////////////////////////////////本项目工程全部代码:
using Autodesk.Revit.UI;
using Autodesk.Revit.DB;
using Autodesk.Revit.Attributes;
using Autodesk.Revit.UI.Selection;
using Autodesk.Revit.DB.Plumbing;
using Autodesk.Revit.DB.Mechanical;
using System.Xml;
using Autodesk.Revit.UI.Events;
using System.Windows.Forms;
using Autodesk.Revit.DB.Events;
using Autodesk.Revit.DB.Architecture;
namespace HelloWorld
{
[Transaction(TransactionMode.Manual)]
[Regeneration(RegenerationOption.Manual)]
public class Test : IExternalCommand
{
public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
{
UIApplication uiApp = commandData.Application;
UIDocument uidoc = uiApp.ActiveUIDocument;
Document doc = uidoc.Document;
if (IsExistLineStyle(doc, "房间边界线"))
{
}
else
{
////生成线样式
using (Transaction ts = new Transaction(doc, "LineStyle"))
{
ts.Start();
Category lineCategory = doc.Settings.Categories.get_Item(BuiltInCategory.OST_Lines);
Category newCategory = doc.Settings.Categories.NewSubcategory(lineCategory, "房间边界线");
Color newColor = new Color(255, 0, 0);
newCategory.LineColor = newColor;
newCategory.SetLineWeight(1, GraphicsStyleType.Projection);
ts.Commit();
}
}
Transaction ts2 = new Transaction(doc, "BIM");
ts2.Start();
Reference refer = uidoc.Selection.PickObject(ObjectType.Element, "");
Room room = doc.GetElement(refer) as Room;
SpatialElementBoundaryOptions opt = new SpatialElementBoundaryOptions();
opt.SpatialElementBoundaryLocation = SpatialElementBoundaryLocation.Finish;
CurveArray array = new CurveArray();
IList(IList(BoundarySegment)) loops = room.GetBoundarySegments(opt);
foreach (IList(BoundarySegment) loop in loops)
{
foreach (BoundarySegment seg in loop)
{
Curve curve = seg.GetCurve();
DetailCurve dc = doc.Create.NewDetailCurve(uidoc.ActiveView, curve);
if (BackLineStyle(doc) != null)
{
SetLineStyle(BackLineStyle(doc), dc);
}
array.Append(dc.GeometryCurve);
}
break;
}
CreateFloor(doc, array);
ts2.Commit();
return Result.Succeeded;
}
//设置线样式
private void SetLineStyle(Category cate, DetailCurve line)
{
ElementId Id = new ElementId(cate.Id.IntegerValue + 1);
foreach (Parameter p in line.Parameters)
{
if (p.Definition.Name == "线样式")
{
p.Set(Id);
break;
}
}
}
//判断线样式是否存在
private bool IsExistLineStyle(Document doc, string Name)
{
Category IsCategory = doc.Settings.Categories.get_Item(BuiltInCategory.OST_Lines);
CategoryNameMap map = IsCategory.SubCategories;
foreach (Category g in map)
{
if (g.Name == Name)
{
return true;
}
}
return false;
}
//搜索目标线样式
private Category BackLineStyle(Document doc)
{
Category lineCategory = doc.Settings.Categories.get_Item(BuiltInCategory.OST_Lines);
CategoryNameMap map = lineCategory.SubCategories;
foreach (Category g in map)
{
if (g.Name == "房间边界线")
{
return g;
}
}
return null;
}
//创建楼板,类型默认 标高默认
private void CreateFloor(Document doc,CurveArray array)
{
FloorType floorType= new FilteredElementCollector(doc).OfClass(typeof(FloorType)).FirstOrDefault() as FloorType;
Level level = new FilteredElementCollector(doc).OfClass(typeof(Level)).OrderBy(o => (o as Level).ProjectElevation).First() as Level;
Floor floor = doc.Create.NewFloor(array,floorType,level,false,XYZ.BasisZ);
}
}
}