Tu sei qui

Revit e Python 3

Prima di descrivere la soluzione finale, la risoluzione dei problemi e l'integrazione con l'API di Revit del componente finora progettato, credo sia doveroso un post sull'integrazione della Shell di IronPython dedicata alle Famiglie. Il post si basa sulla pagina http://wiki.theprovingground.org/revit-api-py-family dove l'autore Nathan Miller descrive sinteticamente le modalità base per lavorare con le Famiglie in Revit attraverso codice Python.
Tuttavia l'autore dà per scontati alcuni passaggi rendendo difficile l'immediata risoluzione degli errori che Python inevitabilmente comunica proprio a causa della loro non esecuzione: obiettivo è descrivere le procedure che Miller illustra attraverso alcune considerazioni personali e risoluzioni ai problemi riscontrati.

Ricordo nuovamente (e suggerisco) anzitutto di scrivere in Add-ins->Configure...->InitScripts il seguente codice così da avere abilitato nella shell superiore l'AutoCompletation (CTRL+Spazio) e le variabili contenenti i rapporti conversione in sistema metrico così da poter moltiplicare i risultati numerici per ottenere il valore corretto e dividere per lavorare con i dati forniti da Revit:

import clr
import math
clr.AddReference('RevitAPI') 
clr.AddReference('RevitAPIUI') 
from Autodesk.Revit.DB import * 
 
app = __revit__.Application
doc = __revit__.ActiveUIDocument.Document
 
mm=1/304.8
cm=1/30.48
m=1/0.3048

 

Dunque creiamo una Famiglia con un Cubo al suo interno definito da TypeParameters altezza,lunghezza e larghezza. Sebbene Miller trascuri questo aspetto sottolineo che è importante creare almeno un Tipo per la famiglia altrimenti il codice non funziona.

Per definire la variabile di riferimento è necessario (in realtà per ottimizzare il codice) attribuire ad una variabile il riferimento al TypeParameter che si trova attraverso un check fra tutti i parametri della famiglia fino a trovare quello corrispondente al nome ricercato
ad es.
height = [a for a in doc.FamilyManager.Parameters if a.Definition.Name=='altezza'][0]
length = [a for a in doc.FamilyManager.Parameters if a.Definition.Name=='lunghezza'][0]
width = [a for a in doc.FamilyManager.Parameters if a.Definition.Name=='larghezza'][0]

Ottenuti i riferimenti ai TypeParameter possiamo eseguire operazioni di stampa a schermo del valore o di variazione degli stessi: facciamo riferimento alle funzioni FamilyManager.Set() e FamilyManager.CurrentType.AsDouble().

ad es.
doc.FamilyManager.Set(height,5*m)   #setta l'altezza al valore 5 m
print doc.FamilyManager.CurrentType.AsDouble(length)/cm   #visualizza la lunghezza 
in cm

Inserire la famiglia all'interno del progetto non è consentito ma tuttavia è possibile farlo all'interno di una Conceptual Mass. Il codice per farlo è il seguente:

t = Transaction(doc, 'Crea un'instanza del cubo.')
 
t.Start()

symbName = 'cubo'     #rappresenta il nome della famiglia all'interno del project browser
 
collector = FilteredElementCollector(doc)
#Miller suggerisce di filtrare gli elementi affinchè il codice consideri solo le conceptual mass. Consiglio di cancellare la riga seguente altrimenti si verifica come nel mio caso (e ci ho messo un po' a capirlo) che il codice ignori il Generic Model, all'interno del quale avevo modellato il mio cubo
collector.OfCategory(BuiltInCategory.OST_Mass)
collector.OfClass(FamilySymbol)

famtypeitr = collector.GetElementIdIterator()
famtypeitr.Reset()

#cerca la famigli nel documento.
for item in famtypeitr:
    famtypeID = item
    famsymb = doc.get_Element(famtypeID)
 
    #se si verifica l'uguaglianza tra il nome 'cubo' e il nome delle famiglie ispezionate esegue le seguenti operazioni
    if famsymb.Family.Name == symbName:
 
        #definisco le coordinate e posiziono la famiglia
        loc = XYZ(0,0,0
        familyInst = doc.FamilyCreate.NewFamilyInstance(loc, famsymb, Structure.StructuralType.NonStructural)
 
t.Commit()

In questi termini posso posizionare infinite istanze lavorando anche sui parametri definiti (a patto che però siano di tipo Instance)

t = Transaction(doc, 'Crea cubi')
 
t.Start()

symbName = 'cubo'
 
#create a filtered element collector set to Category OST_Mass and Class FamilySymbol 
collector = FilteredElementCollector(doc)
#collector.OfCategory(BuiltInCategory.OST_Mass)
collector.OfClass(FamilySymbol)
 
famtypeitr = collector.GetElementIdIterator()
famtypeitr.Reset()

inc = 1
 
for item in famtypeitr:
    famtypeID = item
    famsymb = doc.get_Element(famtypeID)

    if famsymb.Family.Name == symbName:
        for i in range(0,10):
            for j in range(0,10):
 
                loc = XYZ((i*70),(j*70),0) *cm*5
                familyInst = doc.FamilyCreate.NewFamilyInstance(loc, famsymb, Structure.StructuralType.NonStructural)
 
                #modify FamilyInstance parameter using i and j values
                h = abs((60 * math.sin(i))+(60* math.cos(j))) + 10
                param = familyInst.get_Parameter('altezza')
                param.Set(h*cm*10)
 
t.Commit()

A breve il post riguardo l'applicazione di questi semplici principi al mio componente

 

CATEGORIE: 
Technology: 
AllegatoDimensione
Binary Data cubo.rfa220 KB
Binary Data massa.rfa364 KB