I couldn’t get the springs node working, which actually makes some sense when you think about it. Profile families have a bunch of rules which make direct shape imports almost certainly to fail.
However, this was something i was planning on putting together for an account I work with this week, and figured I might as well take the hour or so to build this out this morning and share with the larger community.
The result:
The code:
The good stuff:
####Create profile family from curves####
__author__ = 'Jacob Small'
__twitter__ = '@JacobWSmall'
__version__ = '0.1.0'
####Notes:####
#Creates a new profile family from a closed curve loop and loads it into your project.
#Requires a profile family template (as per authoring a profile family via the UI)
#Requires a single closed curve loop (as per a normal profile family), and other aspects of profile authoring (ie: no too small lines, etc.).
#Requires all curves are on the global XY plane.
#Note that the origin in the Dynamo environment will be the origin in the family environment - orient your stuff acordingly.
import clr #adds the Common Language Runtime to the iron python environment so we can call .net code
clr.AddReference("RevitNodes") #adds the Revit nodes namespace to the CLR
import Revit #imports the Revit namesapce into the iron python environment
#clr.ImportExtensions(Revit.Elements)
clr.ImportExtensions(Revit.GeometryConversion) #adds the Revit Geometry Conversion namespace ot the CLR
from Revit import GeometryConversion as gc #imports the geometry conversion extension to facilitate changing form Dynamo geometry to Revit geometry
clr.AddReference("RevitServices") #adds the RevitServices namespace to the CLR
#import RevitServices
from RevitServices.Persistence import DocumentManager #imports the document manager to the iron python environment
from RevitServices.Transactions import TransactionManager #imports the transaction manager to the iron python environment
clr.AddReference("RevitAPI") #adds the revit api to the CLR
#import Autodesk
from Autodesk.Revit.DB import IFamilyLoadOptions, SaveAsOptions, FilteredElementCollector, View #adds the relevant sections of the Revit API to the iron python environment
activeDoc = DocumentManager.Instance.CurrentDBDocument #sets the active document variable to the current revit document
uiapp = DocumentManager.Instance.CurrentUIApplication #sets the uiapp variable to the current UI application - doing this so we can set up the current app
app = uiapp.Application #sets the app variable tot he current application of the uiapp
class FamilyOption(IFamilyLoadOptions): #defines a new class for the family load opitons, required as the REvit API requires a class for this
def OnFamilyFound(self, familyInUse, overwriteParameterValues): #defines the process for 'when the family already exists'
return True #sets the returned value to be 'true' when the 'when family already exists' process is called
def OnSharedFamilyFound(self, sharedFamily, familyInUse, source, overwriteParameterValues): #defines the process for 'when the family already exists as a shared family'
return True #sets the returned value to be 'true' when the 'hen the family already exists as a shared family' process is callled
curveSet = IN[0] #sets the curve set to the contents of input 0
templatePath = IN[1] #sets the template path for the contents of input 1
familyFileName = IN[2] #sets the family file name to the contents of input 2
directory = IN[3] #sets the family file name to the contents of input 3
filePath = directory+"\\"+familyFileName+".rfa" #creates a valid rfa file path from the family name and the file path
revitCurveSet = [ gc.ProtoToRevitCurve.ToRevitType(curve) for curve in curveSet ] #uses list comprehension to convert the given curves form a Dynamo curve to a Revit curve
saveOptions = SaveAsOptions() #sets the saveOptions to a new saveasoptions object
saveOptions.OverwriteExistingFile = True #sets the property for overwrite existint to 'true' so that the file will be overwritten
famDoc = app.NewFamilyDocument(templatePath) #sets famDoc to a new family reated in the application using the template at the given path
TransactionManager.ForceCloseTransaction(TransactionManager.Instance) #closes any open transactions
TransactionManager.Instance.EnsureInTransaction(famDoc) #starts a new transaction in the family document
#### There is almost certainly a better way to get the view than the next two line, but this worked for me today. Your milage may vary i suggest you review other more inteligent methods. ####
view = FilteredElementCollector(famDoc).OfClass(View).ToElements()[1] #gets the 2nd view from the list of all views in the family document via filtered element collector
famCurves = [famDoc.FamilyCreate.NewDetailCurve(view,curve) for curve in revitCurveSet] #creates a new detail curve for each curve in the revit curve list
TransactionManager.ForceCloseTransaction(TransactionManager.Instance) #forces the transaction to close
TransactionManager.Instance.TransactionTaskDone() #ensure the transaction is done
famDoc.SaveAs(filePath,saveOptions)#saves the family document
loadedFamily = famDoc.LoadFamily(activeDoc,FamilyOption()) #laods the family document into the active document
famClosed = famDoc.Close(False) #closes the family document
OUT = loadedFamily #returns theloaded family into the dynamo workspace
I don’t plan on maintaining this here (typos and all), but the comments are fairly robust so you should be able to reverse engineer whatever you need to modify.