说到Revit批量创建空间,这本不是一个什么困难的事情。Revit本身就自带这样的命令。通过Revit自带命令,在指定的平面视图创建元空间的方式,如下面动图所示:
但我们搞Revit二次开的,要怎么使用代码实现呢? 我尝试了如下思考
一、模拟Revit命令操作,调用Revit固有命令创建。
步骤1、将视图切换到需要创建空间的平面视图;
步骤2、调用Revit命令 分析------>空间;
步骤3、调用Revit命令 自动放置空间。
这样固然能实现相关的功能,但是需要Revit UI的配合,这让我等二次开发人员感觉,对功能的调用是失控的,不能说服自己坦然的使用这种野路子。
调用步骤1,和步骤2的方法,可以通过发送快捷键机制实现,具体代码,等日后补上
那有没有比较靠谱的方式呢?答案是有的,就是下面要介绍的一种方式
二、调用NewSpace2函数创建空间
这个很容易让人接受,它在我们二次开发的API文档中可以很容易的找到。同时它没有任何歧义,至于它的签名为什么有个2,我们就不深究了,因为这丝毫不影响我们对它与生俱来的信任。NewSpace2方法签名如下,
public ICollection<ElementId> NewSpaces2( Level level, Phase phase, View view )
但这个直接被调用的API方法NewSpace2有个先天不足,如果视图包含空间特别多,那么这个方法的响应速度可以慢到你怀疑人生。据说是该方法每创建一个Space都会刷新一下项目,如果按这种推理,那么模型越复杂,待创建空间越多,使用该方法越没有优势。
那么有没有一种,代码写起来比较靠谱(所谓靠谱,我觉得就是有理有据),然后哦执行速度又说的过去的方法呢?答案还是有点,就是下面要介绍的方法。你的卓越追求,终将让你受益匪浅。
三、找到封闭区域内一点,通过该点创建该封闭区域所构成的空间
这个提法有点绕,但这个方法的发现却源自于一种逆向思维。我发现了API中存在一个创建单个空间的方法,函数签名如下:
public Space NewSpace( Level level, Phase phase, UV point )
通过这个方法,我们发现要创建空间,我需要一个点。而通过这一点创建出来的空间,其轮廓就是包含这一个点的封闭区域。那么继续往上倒,也就是说,我们只要拿到当前视图中的所有封闭区域,就能创建对应的空间了。然而空间分割并不会影响平面内封闭区域的划分,可空间分割却会实实在在的成为空间的围护结构,怎么解决这一问题呢?在研究中发现房间分割可以在封闭区域划分中起到相关作用,所以我们会先根据空间分割创建房间分割,然后取到封闭区域。然后再根据封闭区域获得的点,调用开头提供的方法,去创建空间。
不了解空间分割,和房间分割的同学请自行查阅资料吧。这里只是简单提一句,他们只是一种类似辅助线的东西。
通过这种方法创建空间的代码如下:
1、获取视图可以创建空间的位置集合
/// <summary>
/// 获取视图中创建空间的点的信息
/// </summary>
/// <param name="view"></param>
/// <returns></returns>
public static List<XYZ> GetSpacesPoints(View view)
{
Document doc = view.Document;
var level = view.GenLevel;
Parameter para = view.GetParameter(BuiltInParameter.VIEW_PHASE);
ElementId phaseId = para.AsElementId();
var phase = doc.GetElement(phaseId) as Phase;
#region 创建新的节点
List<XYZ> points = new List<XYZ>();
using (SubTransaction sub = new SubTransaction(doc))
{
try
{
sub.Start();
var spaceSeps = GetElements(view, new ElementCategoryFilter(BuiltInCategory.OST_MEPSpaceSeparationLines)).OfType<ModelLine>().ToList();
CurveArray curveArray = new CurveArray();
foreach (var modelLine in spaceSeps)
{
curveArray.Append(modelLine.GeometryCurve);
}
#region 创建房间分割
Plane p = Plane.CreateByNormalAndOrigin(view.ViewDirection, view.Origin);
var sp = SketchPlane.Create(doc, p);
if (!curveArray.IsEmpty)
{
doc.Create.NewRoomBoundaryLines(sp, curveArray, view);
}
#endregion
#region 获取封闭区域
var topology = doc.get_PlanTopology(level, phase);
foreach (PlanCircuit topologyCircuit in topology.Circuits)
{
var point = topologyCircuit.GetPointInside();
var xyz = new XYZ(point.U, point.V, level.ProjectElevation + 1); //适当升高一些
points.Add(xyz);
}
#endregion
}
catch (Exception e)
{
}
finally
{
sub.RollBack();
}
}
#endregion
return points;
}
2、根据点的信息,创建相关空间
public static List<Space> CreateSpaces(View view)
{
List<Space> spaces = new List<Space>();
Document doc = view.Document;
var level = view.GenLevel;
Parameter para = view.GetParameter(BuiltInParameter.VIEW_PHASE);
ElementId phaseId = para.AsElementId();
var phase = doc.GetElement(phaseId) as Phase;
var points = GetSpacesPoints(view);
foreach (var point in points)
{
var oldSpace = doc.GetSpaceAtPoint(point, phase);
if (oldSpace == null)
{
var tempSapce = doc.Create.NewSpace(level, phase, new UV(point.X, point.Y));
spaces.Add(tempSapce);
}
}
return spaces;
}