2015-12-13 1 views
5

J'ai une question pour certains d'entre vous qui sont familiers avec l'API Revit et python:créer et attribuer des sous-catégories dans Revit en utilisant python

J'utilise le paquet de noeuds de printemps dans dynamo pour créer une série assez grande d'objets libres chacun dans leur propre famille. La façon dont fonctionne FamilyInstance.ByGeometry prend une liste de solides et crée une instance de famille pour chacun d'entre eux en utilisant un fichier de modèle de famille. Le résultat est plutôt bon. (Les nœuds de ressorts peuvent être trouvés ici: https://github.com/dimven/SpringNodes)

Cependant, l'inconvénient est que j'ai maintenant environ 200 instances distinctes, donc apporter des changements à chacun est plutôt douloureux. Je pensais au début qu'il serait possible d'utiliser dynamo pour créer une nouvelle sous-catégorie et définir le solide dans chaque instance de la famille à cette nouvelle sous-catégorie. Malheureusement, j'ai réalisé que ce n'est pas possible puisque la dynamo ne peut pas être ouverte dans deux environnements Revit différents simultanément (le projet dans lequel je travaille et chaque instance de la famille). Cela m'amène à voir si je peux le faire en utilisant python. J'ai utilisé du python dans le rhinocéros et je peux très bien m'entendre, mais j'apprends toujours l'API Revit. Mais fondamentalement, mon idée serait de: 1. sélectionner une série d'instances de familles dans l'environnement de projet Revit 2. parcourir chaque instance 3. l'enregistrer dans un emplacement spécifié 4. créer une nouvelle sous-catégorie dans chaque instance de famille (la sous-catégorie serait la même chose pour toutes les instances de la famille) 5. sélectionnez le solide dans chaque cas en 6. Réglez le solide à cette sous-catégorie 7. Fermez l'instance de famille nouvellement créé et sauver

Ma question pour vous Est-ce que cela semble être réalisable en fonction de votre connaissance de l'API Revit?

Un grand merci pour votre temps et vos conseils.


MISE À JOUR:

J'ai trouvé une section dans le api REVIT qui décrit ce que je cherche à faire: http://help.autodesk.com/view/RVT/2015/ENU/?guid=GUID-FBF9B994-ADCB-4679-B50B-2E9A1E09AA48

J'ai fait un premier passage à insérer dans le présent code python du noeud dynamo. Le reste du code fonctionne bien, sauf pour la nouvelle section im ajoutant (voir ci-dessous). S'il vous plaît excuser les variables, je garde simplement avec la logique de l'auteur original du code je suis Hacking:

(Note: les variables sont disponibles en sont dans des tableaux)

#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 

Toute aide ou des conseils à ce section de code serait très appréciée.


MISE À JOUR: Voir le code complet ci-dessous pour le contexte de la section en question:

#Copyright(c) 2015, Dimitar Venkov 
# @5devene, [email protected] 

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." 

Mise à jour:

a pu le faire fonctionner:

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 

Répondre

0

Comme je réponds ed sur votre requête initiale par e-mail, ce que vous visez pour les sons me semble parfaitement réalisable dans l'API Revit. Félicitations pour avoir été aussi loin que vous. En regardant le lien vers le fichier d'aide de Revit API et le guide du développeur que vous citez ci-dessus, il semble que le code doit être exécuté dans le document de famille tout en définissant la famille. Le contexte dans lequel vous essayez de l'exécuter n'est pas clair. Avez-vous utilisé EditFamily pour ouvrir le document de définition de la famille? Dans quel contexte exécutez-vous?

+0

J'ai décidé que plutôt que de faire une boucle dans chaque famille et de l'éditer, j'éditerais le code python original dans le graphique de la dynamo à partir du plugin des nœuds de printemps. Dans le code de ce noeud, les solides sont placés dans une nouvelle famille créée à partir d'un fichier de modèle de famille. La partie du code que j'ai posté opère déjà à l'intérieur de la famille elle-même, créant la géométrie freeform, définissant la catégorie, ajoutant un matériau et ainsi de suite, j'ajoute juste la partie de la sous-catégorie. Je peux essayer de poster le code complet ... – LuebkerJ

+0

Je l'ai juste obtenu pour travailler avec un peu d'aide d'un collège au travail ... d'abord je devais passer la variable pas le nom de la variable dans la partie de sous-catégorie de création. Deuxièmement, je fonctionnais dans le mauvais def pour ma version de revit. J'ai posté le code corrigé comme une mise à jour ci-dessus. – LuebkerJ