簡體   English   中英

使用python在revit中創建和分配子類別

[英]create and assign subcategories in revit using python

對於熟悉Revit API和python的一些人,我有一個問題:

我一直在使用dynamo中的spring nodes包來創建一個相當大的自由對象系列,每個對象都在它們自己的系列中。 FamilyInstance.ByGeometry的工作方式,它采用實體列表,並使用模板系列文件為每個實體創建一個族實例。 結果非常好。 (可以在這里找到spring節點: 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

我已經第一次將它插入到dynamo節點的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

正如我在每封電子郵件中回答您的初始查詢時,您在Revit API中對我的目標完全可行。 恭喜你盡可能地擁有。 查看上面引用的Revit API幫助文件和開發人員指南的鏈接,似乎必須在定義系列時在系列文檔中執行代碼。 您嘗試執行它的上下文不清楚。 您是否使用EditFamily打開家庭定義文檔? 你在執行什么上下文?

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM