C# 和 Python 使用 Revit API 的对比
在 .net 世界中,各种高级语言(如 C#、VB)的编译器会将它们的代码编译成中间语言 IL,IL本身并不知道自己是由哪种高级语言转化而来,我们可以很方便的在一种语言中使用另一种语言编译成的库(dll)。
IronPython 是一种在 .NET 和 Mono 上实现的 Python 语言,目前版本对应的是 Python 2.7。在 Revit 中提供了 IronPython 的支持,Revit API 又是使用 C# 语言编写,所以理论上,我们可以使用 IronPython 来调用 Revit API 中的相关功能。
接下来,我们在 Revit 宏中对比两种语言使用 API 的方式,如果不知道如何使用宏,可以先阅读 。
元素过滤
在 Revit 开发中,元素过滤是最最基础的了,他能从文档中快速找到需要的元素(Element)。
C# 语言的元素过滤
// 从应用程序宏中获得当前文档
Document doc = this.ActiveUIDocument.Document;
// 创建容器,它包含文档中所有的元素
FilteredElementCollector collector = new FilteredElementCollector(doc);
// 在使用 collector 之前,必须给他添加过滤器,这里我们过滤墙
// ElementClassFilter filter = new ElementClassFilter(typeof(Wall));
// var walls = collector.WherePasses(filter).ToElements();
// OfClass 是应用 ElementClassFilter 的便捷写法
var walls = collector.OfClass(typeof(Wall)).ToElements();
Python 语言的元素过滤,注意这里使用 clr.GetClrType(...) 来获得 Type
# 从应用程序宏中获得当前文档
doc = self.ActiveUIDocument.Document
# 创建容器,它包含文档中所有的元素
collector = FilteredElementCollector(doc)
# 在使用 collector 之前,必须给他添加过滤器,这里我们过滤墙
filter = ElementClassFilter(clr.GetClrType(Wall))
walls = collector.WherePasses(filter).ToElements()
# OfClass 是应用 ElementClassFilter 的便捷写法
walls = collector.OfClass(clr.GetClrType(Wall)).ToElements()
元素选择
为了精确选择某类元素,我们通常会定义选择过滤器。选择过滤器必须实现接口:ISelectionFilter
C# 中的定义选择过滤器,这里将过滤墙:
class WallFilter : ISelectionFilter
{
public bool AllowElement(Element elem)
{
return elem is Wall;
}
public bool AllowReference(Reference reference, XYZ position)
{
throw new NotImplementedException();
}
}
Python 中的定义选择过滤器:
class WallFilter(ISelectionFilter):
"""选择过滤器"""
def AllowElement(self, element):
return isinstance(element, Wall)
def AllowReference(self, reference, position):
pass
C# 点选构件,WallFilter 为上文中创建的选择过滤器
// 获取文档中的 Selection,选择元素都是 Seleciton 中的方法
Selection sel = this.ActiveUIDocument.Selection;
// 点选一个构件,获得元素的引用
Reference r = sel.PickObject(ObjectType.Element, new WallFilter(), "请选择一面墙");
// 获取元素
Element e = this.ActiveUIDocument.Document.GetElement(r);
Python 点选构件
# 获取文档中的 Selection,选择元素都是 Seleciton 的方法
sel = self.ActiveUIDocument.Selection
# 点选一个构件,获得元素的引用
r = sel.PickObject(ObjectType.Element, WallFilter(), "请选择一面墙")
# 获取元素
e = self.ActiveUIDocument.Document.GetElement(r)
事物
在 Revit 中修改文档时必须用 Transaction 提交,所谓修改文档指的是新建、删除和修改元素。我们现在创建一个工作平面(Sketchplane)
C#
// 修改模型必须在 transction 中
using (Transaction trans = new Transaction(doc, "创建参照平面")) {
trans.Start(); // 开启事物
// 根据平面法向量和原点创建平面
Plane plane = Plane.CreateByNormalAndOrigin(XYZ.BasisX, XYZ.Zero);
// 通过平面创建工作平面
SketchPlane sketchPlane = SketchPlane.Create(doc, plane);
trans.Commit(); // 提交事物
}
Python 中的事物,这里使用 with 来释放资源,是否跟 C# 中的 using 一样有效,还有待测试。
with Transaction(doc, "CreateSketchPlane") as transaction:
transaction.Start() # 开启事物
# 根据平面法向量和原点创建平面
plane = Plane.CreateByNormalAndOrigin(XYZ.BasisX, XYZ.Zero)
# 通过平面创建工作平面
sketchPlane = SketchPlane.Create(doc, plane)
transaction.Commit() # 提交事物
小结
由以上对比可知,C# 和 Python 使用 Revit API 的方式几乎是一样的,不一样的是语法层面的差别。