The RayBounce function is precious when it comes to checking ceiling heights in order to place components, or to check program compliance. But more often than not, the elements needed “to bounce on” are in a linked model, and the OOTB RayBounce node only works with elements from the current document.
So, I took a look at the API and couldn’t find anything called RayBounce. After a little research I, as always, stumbled upon a post from Jeremy Tammik on The Building Coder that pointed me in the right direction: the ReferenceIntersector class. I then came up with the “RayBounce on linked file” node (Data-Shapes Package, code below). Because Revit doesn’t work internally with units other than feet, I had to come up with a unit conversion workaround. Using the Units and UnitUtils class, I was able to retrieve the UI unit type of the current document and convert the data to/from internal API units.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#Copyright (c) mostafa el ayoubi | |
#www.data-shapes.net 2016 elayoubi.mostafa@gmail.com | |
import clr | |
clr.AddReference('RevitAPI') | |
from Autodesk.Revit.DB import* | |
clr.AddReference('ProtoGeometry') | |
from Autodesk.DesignScript.Geometry import * | |
clr.AddReference('RevitServices') | |
from RevitServices.Persistence import DocumentManager | |
doc = DocumentManager.Instance.CurrentDBDocument | |
#Document UI Units | |
UIunit = Document.GetUnits(doc).GetFormatOptions(UnitType.UT_Length).DisplayUnits | |
#Inputs : Points, Direction, 3D View | |
if isinstance(IN[0],list): | |
points = [XYZ(UnitUtils.ConvertToInternalUnits(i.X,UIunit),UnitUtils.ConvertToInternalUnits(i.Y,UIunit),UnitUtils.ConvertToInternalUnits(i.Z,UIunit)) for i in IN[0]] | |
else: | |
points = [XYZ(UnitUtils.ConvertToInternalUnits(IN[0].X,UIunit),UnitUtils.ConvertToInternalUnits(IN[0].Y,UIunit),UnitUtils.ConvertToInternalUnits(IN[0].Z,UIunit))] | |
direction = XYZ(IN[1].X,IN[1].Y,IN[1].Z) | |
view = UnwrapElement(IN[2]) | |
ex = [] | |
pts = [] | |
ri = ReferenceIntersector(view) | |
ri.FindReferencesInRevitLinks = True | |
for p in points: | |
ref = ri.FindNearest(p,direction) | |
if ref == None: | |
pts.append(None) | |
else: | |
refp = ref.GetReference().GlobalPoint | |
pts.append(Point.ByCoordinates(UnitUtils.ConvertFromInternalUnits(refp.X,UIunit),UnitUtils.ConvertFromInternalUnits(refp.Y,UIunit),UnitUtils.ConvertFromInternalUnits(refp.Z,UIunit))) | |
OUT = pts |
The node is meant to be used in a very similar way to the OOTB RayBounce Node, although I could not find a way to set the amount of bounces (maxBounce). The node will return null values for the points that don’t have an element to bounce on, in order to keep the list structure as similar to the initial one as possible and facilitate data exploitation. I also couldn’t find a way to specify which linked model to perform the RayBouncing on in the API. An easy way to address the problem is to use a 3D view where only the appropriate links are displayed.
I also published a node called “RayBounce on Link Category” (code below) that allows to specify the categories you want your rays to bounce on :
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#Copyright (c) mostafa el ayoubi | |
#www.data-shapes.net 2016 elayoubi.mostafa@gmail.com | |
import clr | |
clr.AddReference('RevitAPI') | |
from Autodesk.Revit.DB import* | |
clr.AddReference('ProtoGeometry') | |
from Autodesk.DesignScript.Geometry import * | |
clr.AddReference('RevitServices') | |
from RevitServices.Persistence import DocumentManager | |
import System | |
doc = DocumentManager.Instance.CurrentDBDocument | |
#Document UI Units | |
UIunit = Document.GetUnits(doc).GetFormatOptions(UnitType.UT_Length).DisplayUnits | |
#Inputs : Points, Direction, 3D View | |
if isinstance(IN[0],list): | |
points = [XYZ(UnitUtils.ConvertToInternalUnits(i.X,UIunit),UnitUtils.ConvertToInternalUnits(i.Y,UIunit),UnitUtils.ConvertToInternalUnits(i.Z,UIunit)) for i in IN[0]] | |
else: | |
points = [XYZ(UnitUtils.ConvertToInternalUnits(IN[0].X,UIunit),UnitUtils.ConvertToInternalUnits(IN[0].Y,UIunit),UnitUtils.ConvertToInternalUnits(IN[0].Z,UIunit))] | |
direction = XYZ(IN[1].X,IN[1].Y,IN[1].Z) | |
view = UnwrapElement(IN[2]) | |
ex = [] | |
pts = [] | |
_category = IN[3] | |
filter = ElementCategoryFilter(System.Enum.ToObject(BuiltInCategory, _category.Id)) | |
ri = ReferenceIntersector(filter,FindReferenceTarget.All,view) | |
ri.FindReferencesInRevitLinks = True | |
for p in points: | |
ref = ri.FindNearest(p,direction) | |
if ref == None: | |
pts.append(None) | |
else: | |
refp = ref.GetReference().GlobalPoint | |
pts.append(Point.ByCoordinates(UnitUtils.ConvertFromInternalUnits(refp.X,UIunit),UnitUtils.ConvertFromInternalUnits(refp.Y,UIunit),UnitUtils.ConvertFromInternalUnits(refp.Z,UIunit))) | |
OUT = pts |
Feel free to comment if you have some improvement ideas. Hope this helps save some time on the job!
Hello. Thank you for the article. I haven’t had luck using the RayBounce nodes. I am getting null returned. Do you have a script I can try using?
LikeLike
Hi clooz, thanks for your comment. Let’s continue this here :
https://forum.dynamobim.com/t/does-raybounce-byorigindirection-work-with-revit-linked-files/7389/4
LikeLike
I am new to this. i need to place family in revit using X,Y,Z co-ordination… X & Y value got from autocad to excel, for z value based on face i need to place a family. ( For example : like placing lights in ceiling based on autocad X&Y, based on revit model Z value). As of now i got script for placing family using X&Y co-ordination from Autocad to Excel to Dynamo. But for Z, i am not getting how to do. Please someone help to find solution.
https://forum.dynamobim.com/t/place-family-using-x-y-z-co-ordination/31949
LikeLike