Create and Export 2D Lines Loop Profile Family

I like to explore a way to create a 2d line loop profile (maybe as simple as a rectangle to begin with) and export it as a generic profile family for creating a sweep in Revit. Any suggestion of the nodes I should look at? Thanks.

I haven’t seen this directly exposed as a node, but it’s certainly doable via the API. I’ll see if I can get a set of API doc links together, perhaps tomorrow evening (not booting the work laptop on weekends anymore).

2 Likes

Springs Package- FamilyInstanceByGeometry
OOTB-PolyCurveBy.ByJointcurve (btw. lines need to be planar)
OOTB-PolyCurve.CloseWithLine
Google

2 Likes

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.

8 Likes

Wow, thanks a lot!!! That’s a lot of information for me to process. Let me try to make it work on my end/

1 Like

Same here. I only use a Chromebook outside of working hours.

1 Like

Was an early start for me (midnight actually), but I had to be up anyway for another call so… shrug
Anyway, good luck with it and let me know how it turns out. :slight_smile:

1 Like

I tried to use a rectangle within Dynamo instead of importing a polygon. The end game is setting up parameters and calculation to generate a straight line loop profile (stadium bowl profile). Is the error message related to the version of Revit (R19) or Dynamo I am using?

Looks like an issue with the copy/paste.

This version of the DYN should be easier to ‘just test’:
New Profile Family From Curves - Share Out.dyn (34.0 KB)

Note that it includes a ‘close all the documents you can’ bit of Python in the purple group. Be VERY careful with this as it will do so without saving (by design because the error message which can be produced by the python will prevent saving). Close everything you care about when running this (including other Revit instances - better safe than sorry).

2 Likes

@jacob.small I think you should give yourself a pat on the back in the form of a self-allocated solution to this post haha.

Great bit of code - thanks for sharing!

1 Like