【问题标题】:How to copy an object in revit API using python如何使用 python 在 revit API 中复制对象
【发布时间】:2020-10-04 23:20:53
【问题描述】:

有没有一种方法可以复制过滤器元素收集器对象? 例如,原始对象指向 0x000000000000156B,我希望复制的对象指向不同的位置,这样我就可以在不更改原始对象的情况下继续进行修改。

这里有一些代码来说明我的想法:

Col1 = FilteredElementCollector(doc).OfCategory(BuiltInCategory.OST_Walls)
#Some code to copy the object and assign it to Col2
Col2 = Col2.WhereElementIsNotElementType().ToElements() #Changing Col2 shouldn't change Col1.

我知道 FilteredElementCollector 类中没有这样的方法,但应该有办法做到这一点,对吧? 我还阅读了有关 deepcopy 的文章,但无法在 Revit 上使用它。

任何帮助将不胜感激,谢谢!

【问题讨论】:

  • Revit 元素数据不能存在于 Revit 文档之外。如果在 Revit 模型中实际上没有元素的第二个副本,则无法制作 Revit 元素的副本。例如,您需要在 Revit 模型中复制一个墙元素(注意这可能导致的所有碰撞警告),然后编辑第二个元素
  • 是的,这是有道理的。我只是想也许收藏家可以被复制。如果我定义了两次相同的收集器,我会得到两个不同的 FilteredElementCollector 对象。如果不必再次定义收集器,我可以只复制我已经拥有的收集器会更容易,但是,正如你所说,这可能是不可能的。
  • 每次您在收集器实例上调用过滤方法(例如.OfCategory().OfClass())时,它们都会返回该实例的修改版本。因此,即使您将更通用的收集器存储在变量中,所有后续对过滤方法的调用也会更改原始收集器
  • 知道了!非常感谢!

标签: python revit-api revit revitpythonshell pyrevit


【解决方案1】:

我通常使用 FilteredElementCollector 方法,将其包装在 Python list 中。然后,您可以组合、优化、拆分、复制、排序 - 基本上可以使用 Python 提供的所有便利来做任何您想做的事情。

对于上述问题,您可以创建FilteredElementCollector,并根据需要将其拆分为列表:

rawWalls = FilteredElementCollector(doc).OfCategory(BuiltInCategory.OST_Walls)

Col1 = list(rawWalls)
print 'There are',len(Col1),'wall types+instances in Col1'

Col2 = list(rawWalls.WhereElementIsNotElementType().ToElements())
print 'There are',len(Col2),'wall instances in Col2'

【讨论】:

  • 您好,感谢您的回答。我不认为这实现了我正在寻找的东西。 Col1 和 Col2 仍然指向同一个 FilteredElementCollector 对象。如果在添加 Col3 =list(rawWalls.WhereElementIsElementType().ToElements()) 之后,您将不会得到任何元素,因为收集器已经被过滤掉了。我的想法是拥有一个静态收集器(我们称之为),创建一个副本,然后将所有过滤器应用于这些副本,以便原始(静态)收集器保持不变。
  • 啊,我明白了。所以在那种情况下,我每次需要时都创建一个新的FilteredElementCollector - 它们非常快。抱歉,我无法提供更多帮助
  • 不用担心,我喜欢将收集器包装在 python 列表中的想法。之后会很方便。是的,重新定义收集器非常快速和容易。谢谢!
【解决方案2】:

您已经知道,无法创建FilteredElementCollector 的副本。但是,您可以通过记录在原始文件上调用了哪些方法并在需要制作副本时复制这些方法调用来创建功能相同的方法。下面的类就是这样做的:

class CopyableFilteredElementCollector(FilteredElementCollector):

    def __init__(self, doc):

        # Initialize the underlying FilteredElementCollector
        FilteredElementCollector.__init__(self, doc)

        # Save the document
        self._doc = doc

        # Calls to methods that constrain the FilteredElementCollector will be recorded here
        self._log = []

    def copy(self):

        # Create a brand new instance
        copy = CopyableFilteredElementCollector(self._doc)

        # Replay the log on the new instance
        for method_name, args in self._log:
            getattr(copy, method_name)(*args)

        # The copy now references the same document as the original,
        # and has had the same methods called on it
        return copy

我们需要重写每个限制FilteredElementCollector 返回的元素的方法,以便在日志中记录其调用。最直接的方法是在类主体中定义覆盖方法,如下所示:

    def OfCategory(self, category):

        # Add an entry to the log containing the name of the method that was called
        # and a tuple of its arguments that can be expanded with the splat operator
        self._log.append(('OfCategory', (category,)))

        # Call the original method
        FilteredElementCollector.OfCategory(self, category)

        # Return self just like the original method does 
        return self

为每个方法定义一个覆盖是重复的,所以让我们使用一些元编程巫术代替:

# Methods of FilteredElementCollector that constrain which elements it returns
constraint_methods = [
    'OfCategory',
    'OfClass',
    'WhereElementIsElementType',
    'WhereElementIsNotElementType',
    'WherePasses',
    # et cetera
]

# A factory function that produces override methods similar to the one defined above
def define_method(method_name):
    def method(self, *args):
        self._log.append((method_name, args))
        getattr(FilteredElementCollector, method_name)(self, *args)
        return self
    return method

# Create an override for each method and add it to the CopyableFilteredElementCollector class 
for method_name in constraint_methods:
    setattr(CopyableFilteredElementCollector, method_name, define_method(method_name))

我不会声称我的方法是一个好主意,但如果您的用例需要复制 FilteredElementCollector 而不是从头开始创建新的,这是一个选择。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-09-21
    • 2014-02-13
    • 2019-11-23
    • 1970-01-01
    • 2013-01-07
    • 2020-04-20
    • 1970-01-01
    • 2020-11-18
    相关资源
    最近更新 更多