Hey people ! It’s good to be back to the forums !
I have an issue with linked elements i’m using a user interface with datashapes i have managed to select the linked element i want to use but i can’t seem to get its faces i’ve tried to get the geometry too but i keep getting the same error message ! Any help would be appreciated !
workaround are bimorphnodes
# links
linked_docs = FilteredElementCollector(doc).OfCategory(BuiltInCategory.OST_RvtLinks).WhereElementIsNotElementType().ToElements()
# linked file
link_document = []
for link in linked_docs:
link_doc = link.GetLinkDocument()
link_document.append(link_doc)
link = link_document[0]
# walls
linked_walls = FilteredElementCollector(link).OfCategory(BuiltInCategory.OST_Walls).WhereElementIsNotElementType().ToElements()
faces_of_walls = []
for elem in linked_walls: #for every element
edges = [] #an empty list for the edges to process
processed = [] #the list of processed edges which we want to keep
geos = elem.get_Geometry(Options()) #the geometry
for geo in geos: #for every geometry found
if geo.__class__ == DB.Solid: #if the geomtry is a solid
faces = geo.Faces #get the faces
for f in faces:
faces_of_walls.append(f)
OUT = faces_of_walls
i think that code can also be a starting point. It return all faces of a wall, from walls in a linked file.
The Bimorph nodes worke just fine ! Thanks for your help !
Is there a way to select the face i need from a linked element without a collector it would be so helpful
you can use pickobject methode
selection = uidoc.Selection #type: Selection
# links
linked_docs = FilteredElementCollector(doc).OfCategory(BuiltInCategory.OST_RvtLinks).WhereElementIsNotElementType().ToElements()
# linked file
link_document = []
for link in linked_docs:
link_doc = link.GetLinkDocument()
link_document.append(link_doc)
link = link_document[0]
# get linked wall
#Prompt user to Select a Linked Element
ref_selected_elements = selection.PickObjects(ObjectType.LinkedElement,"Select Linked Element") #type: Reference
#Get Linked Element ID from Resulting Reference
ref_lnk_id = [ref_selected_element.LinkedElementId for ref_selected_element in ref_selected_elements]
#Get RevitLinkInstance from Selection using ElementID
selected_elements = [doc.GetElement(ref) for ref in ref_selected_elements]
faces_of_walls = []
for elem in selected_elements: #for every element
edges = [] #an empty list for the edges to process
processed = [] #the list of processed edges which we want to keep
geos = elem.get_Geometry(Options()) #the geometry
for geo in geos: #for every geometry found
if geo.__class__ == DB.Solid: #if the geomtry is a solid
faces = geo.Faces #get the faces
for f in faces:
faces_of_walls.append(f)
OUT = faces_of_walls
you have to refactor it, i choose multi-selection.
Hi,
Another solution is to directly select the faces of the linked model.
code Python (compatible with IronPython3 or CPython3, except CPython3 in Revit 2024)
import clr
import sys
import System
from System.Collections.Generic import List
clr.AddReference('ProtoGeometry')
from Autodesk.DesignScript.Geometry import *
import Autodesk.DesignScript.Geometry as DS
clr.AddReference('RevitAPI')
import Autodesk
from Autodesk.Revit.DB import *
import Autodesk.Revit.DB as DB
clr.AddReference('RevitAPIUI')
from Autodesk.Revit.UI import *
from Autodesk.Revit.UI.Selection import *
clr.AddReference('RevitNodes')
import Revit
clr.ImportExtensions(Revit.GeometryConversion)
clr.AddReference('RevitServices')
import RevitServices
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager
doc = DocumentManager.Instance.CurrentDBDocument
uiapp = DocumentManager.Instance.CurrentUIApplication
uidoc = uiapp.ActiveUIDocument
class FaceSelection:
def __new__(cls, *args, **kwargs):
cls.args = args
# name of namespace : "CustomNameSpace" + "_" + shortUUID (8 characters)
# IMPORTANT NOTE Each time you modify this class, you must change the namesapce name.
cls.__namespace__ = "FaceSelection_tEfYX0DHE"
try:
# 1. Try to import the module and class. If it already exists, you've probably already created it once, so you can use it.
module_type = __import__(cls.__namespace__)
return module_type._InnerClassInterface(*cls.args)
except ImportError as ex:
class _InnerClassInterface(ISelectionFilter) :
__namespace__ = cls.__namespace__
def __init__(self):
super().__init__()
def AllowElement(self, e):
return True
def AllowReference(self, ref, point):
if ref.ElementReferenceType == ElementReferenceType.REFERENCE_TYPE_SURFACE:
return True
else:
return False
return _InnerClassInterface(*cls.args)
lst_DSface = []
#
TaskDialog.Show("Selection", "Pick Several Faces")
refs = uidoc.Selection.PickObjects(ObjectType.PointOnElement, FaceSelection(), "Pick Several Faces")
for ref in refs:
# get Face Geometry
sel_elem = doc.GetElement(ref)
if isinstance(sel_elem, RevitLinkInstance):
tf1 = sel_elem.GetTotalTransform()
linkDoc = sel_elem.GetLinkDocument()
elem = linkDoc.GetElement(ref.LinkedElementId)
if isinstance(elem, FamilyInstance):
tf2 = elem.GetTotalTransform()
tf1 = tf1.Multiply(tf2)
face_ref2 = ref.CreateReferenceInLink()
face = elem.GetGeometryObjectFromReference(face_ref2)
lst_DSface.append(face.ToProtoType())
else:
elem = sel_elem
face = elem.GetGeometryObjectFromReference(ref)
lst_DSface.append(face.ToProtoType())
OUT = lst_DSface
Thanks for the reply ! This is for sure helpful but i need to prompt the user to select the face directly on the revit linked model not the element and than collect the faces
This is exactly what i was looking for thank your for the contribution
Hello again good sir ! i’m having a bit of a problew with the surface i get from the selected face .
It seems i can’t use it to host a family type. i’m getting this error
Hi @deejaypein PS the only node i know there get the linked surface/reference is that one @Draxl_Andreas show from bimorph…another way could probably be with genius loci…
Here is an update version with 2 lists at the output
- list Surface
- list Reference
import clr
import sys
import System
from System.Collections.Generic import List
clr.AddReference('ProtoGeometry')
from Autodesk.DesignScript.Geometry import *
import Autodesk.DesignScript.Geometry as DS
clr.AddReference('RevitAPI')
import Autodesk
from Autodesk.Revit.DB import *
import Autodesk.Revit.DB as DB
clr.AddReference('RevitAPIUI')
from Autodesk.Revit.UI import *
from Autodesk.Revit.UI.Selection import *
clr.AddReference('RevitNodes')
import Revit
clr.ImportExtensions(Revit.GeometryConversion)
clr.AddReference('RevitServices')
import RevitServices
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager
doc = DocumentManager.Instance.CurrentDBDocument
uiapp = DocumentManager.Instance.CurrentUIApplication
uidoc = uiapp.ActiveUIDocument
class FaceSelection:
def __new__(cls, *args, **kwargs):
cls.args = args
# name of namespace : "CustomNameSpace" + "_" + shortUUID (8 characters)
# IMPORTANT NOTE Each time you modify this class, you must change the namesapce name.
cls.__namespace__ = "FaceSelection_tEfYX0DHE"
try:
# 1. Try to import the module and class. If it already exists, you've probably already created it once, so you can use it.
module_type = __import__(cls.__namespace__)
return module_type._InnerClassInterface(*cls.args)
except ImportError as ex:
class _InnerClassInterface(ISelectionFilter) :
__namespace__ = cls.__namespace__
def __init__(self):
super().__init__()
def AllowElement(self, e):
return True
def AllowReference(self, ref, point):
if ref.ElementReferenceType == ElementReferenceType.REFERENCE_TYPE_SURFACE:
return True
else:
return False
return _InnerClassInterface(*cls.args)
lst_DSface = []
lst_ref_face = []
rvt_link_instance = []
#
TaskDialog.Show("Selection", "Pick Several Faces")
refs = uidoc.Selection.PickObjects(ObjectType.PointOnElement, FaceSelection(), "Pick Several Faces")
for ref in refs:
# get Face Geometry
sel_elem = doc.GetElement(ref)
if isinstance(sel_elem, RevitLinkInstance):
tf1 = sel_elem.GetTotalTransform()
linkDoc = sel_elem.GetLinkDocument()
elem = linkDoc.GetElement(ref.LinkedElementId)
if isinstance(elem, FamilyInstance):
tf2 = elem.GetTotalTransform()
tf1 = tf1.Multiply(tf2)
face_ref2 = ref.CreateReferenceInLink()
face = elem.GetGeometryObjectFromReference(face_ref2)
lst_DSface.append(face.ToProtoType()[0])
lst_ref_face.append(ref)
#print(ref.ConvertToStableRepresentation(doc))
OUT = lst_DSface, lst_ref_face
then you can use the ‘FamilyInstance.ByReference’ node as mentioned by @sovitek
awesome as always thanks Cyril
and a way with pick points, could probably work as well