简体   繁体   English

如何使用 python 在 revit API 中复制 object

[英]How to copy an object in revit API using python

Is there a way I can copy a Filter Element Collector object?有没有办法可以复制滤芯收集器 object? For example, the original object is pointing at 0x000000000000156B and I want the copied object to be pointing at a different location so I can keep making modificacions without changing the original object.例如,原始 object 指向 0x000000000000156B,我希望复制的 object 指向不同的位置,这样我就可以在不更改原始 ZA8Z6.9331BD4B666AC 的情况下继续进行修改

Here's some code to illustrate my idea:这是一些代码来说明我的想法:

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.

I know there's no such method within the FilteredElementCollector class, but there should be a way to do this, right?我知道 FilteredElementCollector class 中没有这样的方法,但应该有办法做到这一点,对吧? I also read about deepcopy but couldn't get it to work on Revit.我还阅读了有关 deepcopy 的信息,但无法在 Revit 上使用它。

Any help will be highly appreciated, Thanks!任何帮助将不胜感激,谢谢!

I normally use the FilteredElementCollector method by wrapping it in a Python list .我通常通过将FilteredElementCollector方法包装在 Python list中来使用它。 Then you can combine, refine, split, copy, sort - bascially do anything you want to it with all the ease that Python offers.然后您可以组合、优化、拆分、复制、排序 - 基本上可以用 Python 提供的所有便利来做任何您想做的事情。

For your problem above, you could create the FilteredElementCollector , and spin it off into lists as required:对于上述问题,您可以创建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'

As you've already figured out, it's not possible to create a copy of a FilteredElementCollector .正如您已经知道的那样,不可能创建FilteredElementCollector的副本。 However, you could create a functionally identical one by recording which methods are called on the original and duplicating those method calls when you need to make a copy.但是,您可以通过记录在原始文件上调用了哪些方法并在需要制作副本时复制这些方法调用来创建功能相同的方法。 The class below does just that:下面的 class 就是这样做的:

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

We need to override each method that restrict the elements returned by the FilteredElementCollector to record its invocation in the log.我们需要重写每个限制FilteredElementCollector返回的元素的方法,以在日志中记录其调用。 The most straightforward way to do that would be by defining override methods in the class body like this:最直接的方法是在 class 主体中定义覆盖方法,如下所示:

    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

Defining an override for every single method gets repetitive, so let's employ some metaprogramming voodoo instead:为每个方法定义一个覆盖是重复的,所以让我们使用一些元编程巫术代替:

# 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))

I won't go as far as to claim that my approach is a good idea, but it's an option if your use case requires making copies of a FilteredElementCollector rather than creating new ones from scratch.我不会 go 声称我的方法是一个好主意,但如果您的用例需要复制FilteredElementCollector而不是从头开始创建新的,这是一个选择。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM