如何使用python在revit API中复制对象

2024-06-02 13:55:08 发布

您现在位置:Python中文网/ 问答频道 /正文

是否有方法可以复制筛选器元素收集器对象? 例如,原始对象指向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

我们将非常感谢您的帮助,谢谢


Tags: to对象方法代码元素doc情况col2
2条回答

我通常使用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'

正如您已经发现的,不可能创建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的副本而不是从头开始创建新副本,那么这是一个选项

相关问题 更多 >