【问题标题】:Advanced Filtering of Elements in Revit APIRevit API 中的高级图元过滤
【发布时间】:2019-07-25 17:31:27
【问题描述】:

我正在关注此 youtube 视频 (https://www.youtube.com/watch?v=WU_D2qNnuGg&index=7&list=PLc_1PNcpnV5742XyF8z7xyL9OF8XJNYnv) 中显示的示例,该示例说明了 Revit API 中的过滤方法优于通常的迭代。但是我的代码比迭代方法慢得多:
过滤方法 - 0.16 秒
迭代法-0.06秒

我使用过滤方法的代码是:

import Autodesk.Revit.DB as DB
doc=__revit__.ActiveUIDocument.Document
uidoc=__revit__.ActiveUIDocument

height_param_id=DB.ElementId(DB.BuiltInParameter.WALL_USER_HEIGHT_PARAM)
height_param_prov=DB.ParameterValueProvider(height_param_id)
param_equality=DB.FilterNumericEquals() # equality class
height_value_rule=DB.FilterDoubleRule(height_param_prov,param_equality,10,1e-02)
param_filter=DB.ElementParameterFilter(height_value_rule)

# This program significantly slows down for the next line
walls=DB.FilteredElementCollector(doc)\
                        .WherePasses(param_filter)\
                        .ToElementIds()

uidoc.Selection.SetElementIds(walls) 

使用以下代码进行迭代。

from System.Collections.Generic import List 
import Autodesk.Revit.DB as DB

doc=__revit__.ActiveUIDocument.Document
uidoc=__revit__.ActiveUIDocument

sheet_collector=DB.FilteredElementCollector(doc)\
             .OfCategory(DB.BuiltInCategory\
             .OST_Sheets)\
             .WhereElementIsNotElementType()\
             .ToElements()

walls=DB.FilteredElementCollector(doc)\
                        .OfCategory(DB.BuiltInCategory.OST_Walls)\
                        .WhereElementIsNotElementType()\
                        .ToElements()
tallwallsids=[]

for wall in walls:
    heightp=wall.LookupParameter('Unconnected Height')
    if heightp and heightp.AsDouble()==10: 
        tallwallsids.append(wall.Id)

uidoc.Selection.SetElementIds(List[DB.ElementId](tallwallsids)) 

【问题讨论】:

    标签: revit-api revitpythonshell pyrevit


    【解决方案1】:

    如果您考虑这两种方法必须考虑的元素数量,这是有道理的。第一种方法:

    walls=DB.FilteredElementCollector(doc)\
                            .WherePasses(param_filter)\
                            .ToElementIds()
    

    在这种方法中,您要求过滤器考虑模型中的所有元素。这可能有很多元素要通过过滤器。反对:

    walls=DB.FilteredElementCollector(doc)\
                            .OfCategory(DB.BuiltInCategory.OST_Walls)\
                            .WhereElementIsNotElementType()\
                            .ToElements()
    

    在此方法中,您使用 QUICK 过滤器 OfCategory() 和另一个 WhereElementIsNotElementType() 将选择范围缩小到仅 Wall 实例。即使你通过一个简单的for 循环来完成它,这是这里的慢组件,它仍然比通过第一个过滤器传递模型中的所有元素要快。

    你可以像这样创建一个过滤器来优化它:

    walls=DB.FilteredElementCollector(doc)\
                            .OfCategory(DB.BuiltInCategory.OST_Walls)\
                            .WhereElementIsNotElementType()\
                            .WherePasses(param_filter)
                            .ToElements()
    

    这实际上会结合快速类别过滤器、元素类型过滤器和慢速参数过滤器,从而可能成为一个整体更快、更易于阅读的解决方案。

    试一试,让我知道这是否有意义。

    干杯!

    【讨论】:

    • 这就是原因。现在完成任务大约需要 0.035 秒。谢谢老兄,这困扰了我一段时间。
    【解决方案2】:

    什么迭代方法?

    如今,过滤元素收集器通常是检索和迭代 Revit 数据库元素的唯一方法。

    过滤后的元素收集器本身可能很快。

    如果你有大量的墙并且你的内存有限,那么调用ToElementIds 可能会消耗大量资源。

    SetElementIds 也可能需要时间。

    查看filtered element collector by pipe system types 上广泛的 Revit API 论坛讨论以了解更多信息。

    我建议您提供一个complete minimal reproducible sample case,并为每个方法调用配备基准代码,以证明性能下降。

    【讨论】:

    • 感谢杰里米的回复。我已更新问题以包含相关代码。我的问题不是关于过滤元素收集器,而是将 WherePasses 与过滤元素收集器一起使用,这大大减慢了程序(几乎是 0.1 秒)。无论模型中有多少墙,这种情况都会发生。
    猜你喜欢
    • 1970-01-01
    • 2011-09-26
    • 2015-04-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-06-18
    • 1970-01-01
    • 2013-09-28
    相关资源
    最近更新 更多