Hi! i’d like to get the Model-in-Place Element level or workplane. I have the following code so far but it’s not working…This element is the one of the index 184 which level resulted in “null”.
import clr
clr.AddReference('RevitAPI')
from Autodesk.Revit.DB import *
clr.AddReference("RevitNodes")
import Revit
clr.ImportExtensions(Revit.Elements)
def GetLevel(item):
val = None
if hasattr(item, "LevelId"):
val = item.Document.GetElement(item.LevelId)
if val: return val
if hasattr(item, "Level"):
val = item.Level
if val: return val
if hasattr(item, "GenLevel"):
val = item.GenLevel
if val: return val
if hasattr(item, "SketchPlane"):
val = item.SketchPlane
if val: return val
if not val:
try: return item.Document.GetElement(item.get_Parameter(BuiltInParameter.INSTANCE_REFERENCE_LEVEL_PARAM).AsElementId())
except:
try: return item.Document.GetElement(item.get_Parameter(BuiltInParameter.INSTANCE_SCHEDULE_ONLY_LEVEL_PARAM).AsElementId())
except: return None
items = UnwrapElement(IN[0])
if isinstance(IN[0], list): OUT = [GetLevel(x) for x in items]
else: OUT = GetLevel(items)
After just a quick look it doesn’t appear that in-place families have reference levels or planes. The geometries do, but the top level family itself does not. You would have to query the geometries within the family to get that information. I didn’t see an obvious way to get them, but it can likely be done through the API somehow.
As I said, those parameters are for the individual pieces of geometry (as you’ve shown) within the family, not the family itself. From the little bit of time I spent looking, I did not see an obvious way to get those geometries (and therefore their parameters) directly from the in-place family. That’s not to say it isn’t possible, I just didn’t see anything pointing towards the next step. I’d do some research into the API for in-place families.
If you edit the Model In Place family, and select the Extrusion solid for example using a Select Model Element node and get the parameter value by name for “Work Plane”, the node will return the solid hosting level, but the thing is the In Places families are not accessible via the API, yet, there is a wishlist for adding this functionality to the API… I guess we need to wait for this one
@Daniel_Woodcock1, it looks like you have the editor open and have manually selected the in-place family geometry. The geometry itself has a level parameter that is accessible, but do you know of a way to get the in-place geometry from the family?
@Daniel_Woodcock1 the family category specified in the IN Place model (Floors), permits a level outside the family editor, an Element.GetParameterValueByName can get that, but if the family category is a Generic Model for example, that hosting level does not show in the Properties palette, unless the In place family is edited , and the geometry selected
@Daniel_Woodcock1 nice workaround ,
here is a variant with the same process for levels and workplanes
import clr
import System
from System.Collections.Generic import List
clr.AddReference("RevitServices")
import RevitServices
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager
doc = DocumentManager.Instance.CurrentDBDocument
clr.AddReference("RevitAPI")
from Autodesk.Revit.DB import *
def to_list(obj1):
if hasattr(obj1,"__iter__"): return obj1
else: return [obj1]
def myRollBack(func):
def wrapper(*args, **kwargs):
TransactionManager.Instance.ForceCloseTransaction()
t = Transaction(doc, func.__name__)
t.Start()
ret = func(*args, **kwargs)
t.RollBack()
return ret
return wrapper
def get_WorkPlane(elem):
# sub function
@myRollBack
def getSubIds(elem):
eIds = doc.Delete(elem.Id)
return eIds
# main function
lstElem = [doc.GetElement(id) for id in getSubIds(elem)]
for e in lstElem:
if isinstance(e, Extrusion):
namePlane = e.Sketch.SketchPlane.Name
planeZ = e.Sketch.SketchPlane.GetPlane().Origin.Z
# get Levels and Reference Plane
typed_list = List[BuiltInCategory]([BuiltInCategory.OST_CLines, BuiltInCategory.OST_Levels])
filtercat = ElementMulticategoryFilter(typed_list)
fecMultiCat = FilteredElementCollector(doc).WherePasses(filtercat).WhereElementIsNotElementType().ToElements().FindAll(lambda x : x.Name == namePlane)
if fecMultiCat.Count == 1:
return fecMultiCat[0]
else:
#filter by Z
for j in fecMultiCat:
if j.Category.Id == ElementId(BuiltInCategory.OST_CLines) and j.GetPlane().Origin.Z == planeZ:
return j
inPlaceElems = to_list(UnwrapElement(IN[0]))
outlist = []
for e in inPlaceElems:
if isinstance(e, FamilyInstance) and e.Symbol.Family.IsInPlace:
outlist.append(get_WorkPlane(e))
OUT = outlist
Is there a way to merge these scripts into an unique python script in order to get the level from all elements such as Model-in-place (extrusion, sweep, blend, revolve, swept blend) and Revit families?
import clr
import System
from System.Collections.Generic import List
clr.AddReference("RevitServices")
import RevitServices
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager
doc = DocumentManager.Instance.CurrentDBDocument
clr.AddReference("RevitAPI")
from Autodesk.Revit.DB import *
def to_list(obj1):
if hasattr(obj1,"__iter__"): return obj1
else: return [obj1]
def myRollBack(func):
def wrapper(*args, **kwargs):
TransactionManager.Instance.ForceCloseTransaction()
t = Transaction(doc, func.__name__)
t.Start()
ret = func(*args, **kwargs)
t.RollBack()
return ret
return wrapper
def get_LevelInPlace(elem):
# sub function
@myRollBack
def getSubIds(elem):
eIds = doc.Delete(elem.Id)
return eIds
# main function
lstElem = [doc.GetElement(id) for id in getSubIds(elem)]
for e in lstElem:
if isinstance(e, Extrusion):
namePlane = e.Sketch.SketchPlane.Name
planeZ = e.Sketch.SketchPlane.GetPlane().Origin.Z
filter = System.Predicate[System.Object](lambda x : x.Name == namePlane)
lvl = List[Element](FilteredElementCollector(doc).OfCategory( BuiltInCategory.OST_Levels).WhereElementIsNotElementType().ToElements()).Find(filter)
return lvl
def get_Level(item):
if hasattr(item, "LevelId"):
lvl = doc.GetElement(item.LevelId)
elif hasattr(item, "Level"):
lvl = item.Level
elif hasattr(item, "GenLevel"):
lvl = item.GenLevel
elif hasattr(item, "ReferenceLevel"):
lvl = doc.GetElement(item.ReferenceLevel.Id)
else:
lvl = None
if lvl is not None:
return lvl
else:
for bip in [BuiltInParameter.INSTANCE_REFERENCE_LEVEL_PARAM, BuiltInParameter.INSTANCE_SCHEDULE_ONLY_LEVEL_PARAM, BuiltInParameter.SCHEDULE_LEVEL_PARAM]:
para = item.get_Parameter(bip)
if para is not None:
lvl = doc.GetElement(para.AsElementId())
if lvl is not None:
return lvl
return None
inPlaceElems = to_list(UnwrapElement(IN[0]))
outlist = []
for e in inPlaceElems:
if isinstance(e, FamilyInstance):
if e.Symbol.Family.IsInPlace:
outlist.append(get_LevelInPlace(e))
else:
outlist.append(get_Level(e))
else:
outlist.append(get_Level(e))
OUT = outlist
Hi! Nice script @c.poupin , however it’s not working for other model-in-place types besides extrusion… Is there a way to add the other types like sweep, blend, revolve, swept blend too?