6

对于熟悉 Revit API 和 python 的一些人,我有一个问题:

我一直在使用 dynamo 中的 spring 节点包来创建一个相当大的一系列自由形式对象,每个对象都属于他们自己的家族。FamilyInstance.ByGeometry 的工作方式是获取一个实体列表并使用模板族文件为每个实体创建一个族实例。结果相当不错。(弹簧节点可以在这里找到:https ://github.com/dimven/SpringNodes )

但是,缺点是现在我有大约 200 个单独的实例,因此对每个实例进行更改是相当痛苦的。起初我认为可以使用 dynamo 创建一个新的子类别并将每个族实例中的实体设置为这个新的子类别。不幸的是,我意识到这是不可能的,因为 dynamo 无法同时在两个不同的 Revit 环境中打开(我正在从事的项目和该系列的每个实例)。这让我想看看我是否可以使用 python 来做到这一点。

我在 rhino 中使用过 python 并且相处得很好,但是我仍在学习 Revit API。但基本上我的想法是: 1. 在 Revit 项目环境中选择一系列族实例 2. 循环遍历每个实例 3. 将其保存到指定位置 4. 在每个族实例中创建一个新的子类别(子类别将所有选定的族实例都相同) 5. 在每个实例中选择实体 6. 将实体设置为这个新创建的子类别 7. 关闭族实例并保存

我的问题是,根据您对 Revit API 的了解,这听起来是否可以实现?

非常感谢您的时间和建议。


更新:

我在 revit api 中找到了描述我想要做什么的部分:http ://help.autodesk.com/view/RVT/2015/ENU/?guid=GUID-FBF9B994-ADCB-4679-B50B -2E9A1E09AA48

我已经完成了将其插入发电机节点的 python 代码的第一步。其余代码工作正常,除了我添加的新部分(见下文)。请原谅变量,我只是与我正在破解的代码的原始作者的逻辑保持一致:

(注意:进来的变量是数组)

#set subcategory    
try:
     #create new sucategory
     fam_subcat = famdoc.Settings.Categories.NewSubcategory(fam_cat, get_Item(subcat1.Name))                

     #assign the mataterial(fam_mat.Id) to the subcategory
     fam_subcat.Material = famdoc.GetElement(fam_mat.Id)

     #assign the subcategory to the element (s2)
     s2.Subcategory = fam_subcat
except: pass

对于这部分代码的任何帮助或建议将不胜感激。


更新:有关相关部分的上下文,请参见下面的完整代码:

#Copyright(c) 2015, Dimitar Venkov
# @5devene, dimitar.ven@gmail.com

import clr
import System
from System.Collections.Generic import *

pf_path = System.Environment.GetFolderPath(System.Environment.SpecialFolder.ProgramFilesX86)
import sys
sys.path.append("%s\IronPython 2.7\Lib" %pf_path)
import traceback

clr.AddReference('ProtoGeometry')
from Autodesk.DesignScript.Geometry import *

clr.AddReference("RevitServices")
import RevitServices
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager
doc = DocumentManager.Instance.CurrentDBDocument
app = DocumentManager.Instance.CurrentUIApplication.Application

clr.AddReference("RevitAPI")
from Autodesk.Revit.DB import *
from Autodesk.Revit.DB.Structure import StructuralType

clr.AddReference("RevitNodes")
import Revit
clr.ImportExtensions(Revit.Elements)
clr.ImportExtensions(Revit.GeometryConversion)

def tolist(obj1):
    if hasattr(obj1,"__iter__"): return obj1
    else: return [obj1]

def output1(l1):
    if len(l1) == 1: return l1[0]
    else: return l1

def PadLists(lists):
    len1 = max([len(l) for l in lists])
    for i in xrange(len(lists)):
        if len(lists[i]) == len1:
            continue
        else:
            len2 = len1 - len(lists[i])
            for j in xrange(len2):
                lists[i].append(lists[i][-1])
    return lists

class FamOpt1(IFamilyLoadOptions):
    def __init__(self):
        pass
    def OnFamilyFound(self,familyInUse, overwriteParameterValues):
        return True
    def OnSharedFamilyFound(self,familyInUse, source, overwriteParameterValues):
        return True

geom = tolist(IN[0])
fam_path = IN[1]
names = tolist(IN[2])
category = tolist(IN[3])
material = tolist(IN[4])
isVoid = tolist(IN[5])
subcategory = tolist(IN[6])

isRvt2014 = False
if app.VersionName == "Autodesk Revit 2014": isRvt2014 = True
units = doc.GetUnits().GetFormatOptions(UnitType.UT_Length).DisplayUnits
factor = UnitUtils.ConvertToInternalUnits(1,units)
acceptable_views = ["ThreeD", "FloorPlan", "EngineeringPlan", "CeilingPlan", "Elevation", "Section"]
origin = XYZ(0,0,0)
str_typ = StructuralType.NonStructural

def NewForm_background(s1, name1, cat1, isVoid1, mat1, subcat1):
    t1 = TransactionManager.Instance
    TransactionManager.ForceCloseTransaction(t1)
    famdoc = doc.Application.NewFamilyDocument(fam_path)
    message = None
    temp_path = System.IO.Path.GetTempPath()
    sat_path = "%s%s.sat" % (temp_path, name1)
    try:
        if factor != 1:
            s1 = s1.Scale(factor)
        sat1 = Geometry.ExportToSAT(s1, sat_path)
        satOpt = SATImportOptions()
        satOpt.Placement = ImportPlacement.Origin
        satOpt.Unit = ImportUnit.Foot
        view_fec = FilteredElementCollector(famdoc).OfClass(View)
        view1 = None
        for v in view_fec:
            if str(v.ViewType) in acceptable_views:
                view1 = v
                break
        t1.EnsureInTransaction(famdoc)
        satId = famdoc.Import(sat1, satOpt, view1)
        opt1 = Options()
        opt1.ComputeReferences = True
        el1 = famdoc.GetElement(satId)
        geom1 = el1.get_Geometry(opt1)
        enum = geom1.GetEnumerator()
        enum.MoveNext()
        geom2 = enum.Current.GetInstanceGeometry()
        enum2 = geom2.GetEnumerator()
        enum2.MoveNext()
        s1 = enum2.Current
        famdoc.Delete(satId)
        TransactionManager.ForceCloseTransaction(t1)
        System.IO.File.Delete(sat_path)
    except:
        message = traceback.format_exc()
        pass
    if message == None:
        try:
            save_path = "%s%s.rfa" % (temp_path, name1)
            SaveAsOpt = SaveAsOptions()
            SaveAsOpt.OverwriteExistingFile = True
            t1.EnsureInTransaction(famdoc)
            #set the category
            try:
                fam_cat = famdoc.Settings.Categories.get_Item(cat1.Name)
                famdoc.OwnerFamily.FamilyCategory = fam_cat
            except: pass
            s2 = FreeFormElement.Create(famdoc,s1)
            if isVoid1:
                void_par = s2.get_Parameter("Solid/Void")
                void_par.Set(1)
                void_par2 = famdoc.OwnerFamily.get_Parameter("Cut with Voids When Loaded")
                void_par2.Set(1)
            else: #voids do not have a material value
                try:
                    mat_fec = FilteredElementCollector(famdoc).OfClass(Material)
                    for m in mat_fec:
                        if m.Name == mat1:
                            fam_mat = m
                            break
                    mat_par = s2.get_Parameter("Material")
                    mat_par.Set(fam_mat.Id)
                except: pass
            #set subcategory    
            try:
                #create new sucategory
                fam_subcat = document.Settings.Categories.NewSubcategory(document.OwnerFamily.FamilyCategory, get_Item(subcat1.Name))               

                #assign the mataterial(fam_mat.Id) to the subcategory
                fam_subcat.Material = famdoc.GetElement(fam_mat.Id)

                #assign the subcategory to the element (s2)
                s2.Subcategory = fam_subcat
            except: pass

            TransactionManager.ForceCloseTransaction(t1)
            famdoc.SaveAs(save_path, SaveAsOpt)
            family1 =  famdoc.LoadFamily(doc, FamOpt1())
            famdoc.Close(False)
            System.IO.File.Delete(save_path)
            symbols = family1.Symbols.GetEnumerator()
            symbols.MoveNext()
            symbol1 = symbols.Current
            t1.EnsureInTransaction(doc)
            if not symbol1.IsActive: symbol1.Activate()
            inst1 = doc.Create.NewFamilyInstance(origin, symbol1, str_typ)
            TransactionManager.ForceCloseTransaction(t1)
            return inst1.ToDSType(False), family1.ToDSType(False)
        except:
            message = traceback.format_exc()
            return message
    else:
        return message

def NewForm_background_R16(s1, name1, cat1, isVoid1, mat1, subcat1):
    t1 = TransactionManager.Instance
    TransactionManager.ForceCloseTransaction(t1)
    famdoc = doc.Application.NewFamilyDocument(fam_path)
    message = None
    temp_path = System.IO.Path.GetTempPath()
    sat_path = "%s%s.sat" % (temp_path, name1)
    try:
        if factor != 1:
            s1 = s1.Scale(factor)
        sat1 = Geometry.ExportToSAT(s1, sat_path)
        satOpt = SATImportOptions()
        satOpt.Placement = ImportPlacement.Origin
        satOpt.Unit = ImportUnit.Foot
        view_fec = FilteredElementCollector(famdoc).OfClass(View)
        view1 = None
        for v in view_fec:
            if str(v.ViewType) in acceptable_views:
                view1 = v
                break
        t1.EnsureInTransaction(famdoc)
        satId = famdoc.Import(sat1, satOpt, view1)
        opt1 = Options()
        opt1.ComputeReferences = True
        el1 = famdoc.GetElement(satId)
        geom1 = el1.get_Geometry(opt1)
        enum = geom1.GetEnumerator()
        enum.MoveNext()
        geom2 = enum.Current.GetInstanceGeometry()
        enum2 = geom2.GetEnumerator()
        enum2.MoveNext()
        s1 = enum2.Current
        famdoc.Delete(satId)
        TransactionManager.ForceCloseTransaction(t1)
        System.IO.File.Delete(sat_path)
    except:
        message = traceback.format_exc()
        pass
    if message == None:
        try:
            save_path = "%s%s.rfa" % (temp_path, name1)
            SaveAsOpt = SaveAsOptions()
            SaveAsOpt.OverwriteExistingFile = True
            t1.EnsureInTransaction(famdoc)
            #set the category
            try:
                fam_cat = famdoc.Settings.Categories.get_Item(cat1.Name)
                famdoc.OwnerFamily.FamilyCategory = fam_cat
            except: pass
            s2 = FreeFormElement.Create(famdoc,s1)
            if isVoid1:
                void_par = s2.LookupParameter("Solid/Void")
                void_par.Set(1)
                void_par2 = famdoc.OwnerFamily.LookupParameter("Cut with Voids When Loaded")
                void_par2.Set(1)
            else: #voids do not have a material value
                try:
                    mat_fec = FilteredElementCollector(famdoc).OfClass(Material)
                    for m in mat_fec:
                        if m.Name == mat1:
                            fam_mat = m
                            break
                    mat_par = s2.LookupParameter("Material")
                    mat_par.Set(fam_mat.Id)
                except: pass

            #apply same subcategory code as before
            #set subcategory    
            try:
                #create new sucategory
                fam_subcat = famdoc.Settings.Categories.NewSubcategory(fam_cat, get_Item(subcat1.Name))             

                #assign the mataterial(fam_mat.Id) to the subcategory
                fam_subcat.Material = famdoc.GetElement(fam_mat.Id)

                #assign the subcategory to the element (s2)
                s2.Subcategory = fam_subcat
            except: pass


            TransactionManager.ForceCloseTransaction(t1)
            famdoc.SaveAs(save_path, SaveAsOpt)
            family1 =  famdoc.LoadFamily(doc, FamOpt1())
            famdoc.Close(False)
            System.IO.File.Delete(save_path)
            symbols = family1.GetFamilySymbolIds().GetEnumerator()
            symbols.MoveNext()
            symbol1 = doc.GetElement(symbols.Current)
            t1.EnsureInTransaction(doc)
            if not symbol1.IsActive: symbol1.Activate()
            inst1 = doc.Create.NewFamilyInstance(origin, symbol1, str_typ)
            TransactionManager.ForceCloseTransaction(t1)
            return inst1.ToDSType(False), family1.ToDSType(False)
        except:
            message = traceback.format_exc()
            return message
    else:
        return message

if len(geom) == len(names) == len(category) == len(isVoid) == len(material) == len(subcategory):
    if isRvt2014:
        OUT = output1(map(NewForm_background, geom, names, category, isVoid, material, subcategory))
    else:
        OUT = output1(map(NewForm_background_R16, geom, names, category, isVoid, material, subcategory))
elif len(geom) == len(names):
    padded = PadLists((geom, category, isVoid, material, subcategory))
    p_category = padded[1]
    p_isVoid = padded[2]
    p_material = padded[3]
    p_subcategory = padded [4]
    if isRvt2014:
        OUT = output1(map(NewForm_background, geom, names, p_category, p_isVoid, p_material, p_subcategory))
    else:
        OUT = output1(map(NewForm_background_R16, geom, names, p_category, p_isVoid, p_material, subcategory))
else: OUT = "Make sure that each geometry\nobject has a unique family name."

更新:

能够让它工作:

    try:
        #create new sucategory
        fam_subcat = famdoc.Settings.Categories.NewSubcategory(famdoc.OwnerFamily.FamilyCategory, subcat1)          

        #assign the mataterial(fam_mat.Id) to the subcategory
        #fam_subcat.Material = famdoc.GetElement(fam_mat.Id)

        #assign the subcategory to the element (s2)
        s2.Subcategory = fam_subcat
    except: pass
4

1 回答 1

1

正如我在每封电子邮件的初始查询中回答的那样,您的目标在 Revit API 中对我来说听起来完全可行。恭喜你取得了尽可能多的成绩。查看您上面引用的 Revit API 帮助文件和开发人员指南的链接,似乎必须在定义族时在族文档中执行代码。您尝试执行它的上下文尚不清楚。有没有用 EditFamily 打开族定义文档?你在什么环境下执行?

于 2015-12-14T09:02:42.263 回答