Raybouncing in Python

Hi community,

i’m transfering a dynamo script that i made to python (pyrevit).
In the dynamo-script i’m using the a raybounce node from data-shapes (RayBounce On Linked Model) , see the python code below on which node runs.

for the moment i’m struggeling in tranfering this to working code in python without using the designscript import (wich is dependend on dynamo).

Any idea or insights?

#Copyright (c) mostafa el ayoubi
#Node-mode www.data-shapes.net 2016 elayoub.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

try:
	UIunit = Document.GetUnits(doc).GetFormatOptions(UnitType.UT_Length).DisplayUnits
except:
	UIunit = Document.GetUnits(doc).GetFormatOptions(SpecTypeId.Length).GetUnitTypeId()


#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 = []
elems = []

ri = ReferenceIntersector(view)
ri.FindReferencesInRevitLinks = True

for p in points:
	ref = ri.FindNearest(p,direction)
	if ref == None:
		pts.append(None)
		elems.append(None)
	else:
		refel = ref.GetReference()
		linkinstance = doc.GetElement(refel.ElementId)
		try:
			elem = linkinstance.GetLinkDocument().GetElement(refel.LinkedElementId)
			elems.append(elem)
			refp = ref.GetReference().GlobalPoint
			pts.append(Point.ByCoordinates(UnitUtils.ConvertFromInternalUnits(refp.X,UIunit),UnitUtils.ConvertFromInternalUnits(refp.Y,UIunit),UnitUtils.ConvertFromInternalUnits(refp.Z,UIunit)))
		except:
			if not IN[3]:
				elems.append(linkinstance)
				refp = ref.GetReference().GlobalPoint
				pts.append(Point.ByCoordinates(UnitUtils.ConvertFromInternalUnits(refp.X,UIunit),UnitUtils.ConvertFromInternalUnits(refp.Y,UIunit),UnitUtils.ConvertFromInternalUnits(refp.Z,UIunit)))
			else:
				pass


OUT = pts , elems

@AlexanderVandenbergh ,

at my knowleage you have also preset your inputs…

You have to be in the right view with right elements f.e. finished floor or ceiling.

also you have to deligate the vector in +/- direction.

KR

Andreas

1 Like

Hi,
you can replace this
pts.append(Point.ByCoordinates(UnitUtils.ConvertFromInternalUnits(refp.X,UIunit),UnitUtils.ConvertFromInternalUnits(refp.Y,UIunit),UnitUtils.ConvertFromInternalUnits(refp.Z,UIunit)))

by

pts.append(UnitUtils.ConvertFromInternalUnits(refp.X,UIunit),UnitUtils.ConvertFromInternalUnits(refp.Y,UIunit),UnitUtils.ConvertFromInternalUnits(refp.Z,UIunit))

and remove this

clr.AddReference('ProtoGeometry')
from Autodesk.DesignScript.Geometry import *

clr.AddReference('RevitServices')
from RevitServices.Persistence import DocumentManager

doc = DocumentManager.Instance.CurrentDBDocument

additional note

  • it will be necessary to replace the doc variable with the method given by pyRevit and points will be not visible in model (there is maybe a geometry helper function in pyRevit)
  • replace if not IN[3]: by …

I think this topic should be on the pyRevit forum (which will help other pyRevit users in the same situation)

3 Likes

Well this is what i got so far.
Seems like something is working but not as it should.

i tried placing a simple generic family at the calculation points for my room height calculation.
But they all end up at the bottom around the same region (see screenshot).
any ideas?

i also wierdly seems to clash alot with a beamtype not with floors wich i find strange as well.

To recap the idea is to retrieve the roomheight in a linked model by raybouncing from the roombase point in the Z-direction and then calculate the diffence.

so the blocks of the base points should ba all over the place instead of in one point.

# =======================================================================
# IMPORTS
# =======================================================================
import sys
sys.path.append(r'H:\\_GROEPEN\\CAD\\DEV\\Tools\\CMRP')

from pyrevit import script
from pyrevit import UI
from pyrevit import revit
from Autodesk.Revit.UI import *
from Autodesk.Revit.UI.Selection import *
from Autodesk.Revit.DB import *
from Autodesk.Revit.DB.Structure import StructuralType

from CMRPGUI import *
from CMRP import *

# Doc & App
# -----------------------------------------------------------------------
doc = revit.doc
uidoc = revit.uidoc

links = link_selection(doc)

room_points = []
room_Id = []

for link in links:
        link = link.GetLinkDocument()
        rooms = FilteredElementCollector(link).OfCategory(BuiltInCategory.OST_Rooms).ToElements()
        # Get rooms information from linked model
        # -----------------------------------------------------------------------
        for room in rooms:
                if isinstance(room.Location, LocationPoint):
                        room_points.append(room.Location.Point)
                        room_Id.append(room.UniqueId)


views = FilteredElementCollector(doc).OfClass(View).WhereElementIsNotElementType().ToElements()
for x in views:
    if x.Name == "ray3D":
        view = x
        break

#Document UI Units
try:
	UIunit = Document.GetUnits(doc).GetFormatOptions(UnitType.UT_Length).DisplayUnits
except:
	UIunit = Document.GetUnits(doc).GetFormatOptions(SpecTypeId.Length).GetUnitTypeId()

# translation_vector = XYZ(0, 0, 1000)

# # Translate each point in room_points so that it is above the floor
# for i in room_points:
#     i = i.Add(translation_vector)

# #Inputs : Points, Direction, 3D View
if isinstance(room_points,list):
	points = [XYZ(UnitUtils.ConvertToInternalUnits(i.X,UIunit),UnitUtils.ConvertToInternalUnits(i.Y,UIunit),UnitUtils.ConvertToInternalUnits(i.Z,UIunit)) for i in room_points]
else:
	points = [XYZ(UnitUtils.ConvertToInternalUnits(room_points.X,UIunit),UnitUtils.ConvertToInternalUnits(room_points.Y,UIunit),UnitUtils.ConvertToInternalUnits(room_points.Z,UIunit))]

direction = XYZ(0,0,1)

ex = []
pts = []
elems = []

ri = ReferenceIntersector(view)
ri.FindReferencesInRevitLinks = True

# # Find nearest reference for each point and compute height
heights = []
# for p in points:
#     ref = ri.FindNearest(p, direction)
#     if ref is not None:
#         refel = ref.GetReference()
#         link_instance = doc.GetElement(refel.ElementId)
#         try:
#             elem = link_instance.GetLinkDocument().GetElement(refel.LinkedElementId)
#             print(elem.Id)
#             refp = ref.GetReference().GlobalPoint
#             height = UnitUtils.ConvertFromInternalUnits(refp.Z, UIunit) - UnitUtils.ConvertFromInternalUnits(p.Z, UIunit)
#             heights.append(height)
#             print("Element: {}, Height: {}".format(elem.Name, height))
#         except:
#             pass
#     else:
#         heights.append(None)
#         print("No reference found")

# # Print calculated heights
# for height, Id in zip(heights, room_Id):
#     print(Id)
#     print(height)

# ...

def get_type_by_name(type_name):
    param_type = ElementId(BuiltInParameter.ALL_MODEL_TYPE_NAME)
    f_param = ParameterValueProvider(param_type)
    evaluator = FilterStringEquals()
    f_rule = FilterStringRule(f_param, evaluator, type_name, True)
    
    filter_type_name = ElementParameterFilter(f_rule)
    
    return FilteredElementCollector(doc).WherePasses(filter_type_name).WhereElementIsElementType().FirstElement()



# element= doc.Create.NewFamilyInstance(pt, symbol, StructuralType.NonStructural)

# ...

# Find nearest reference for each point and compute height
with Transaction(doc, "Place Generic Model Instances") as t:
    t.Start()
    symbol = get_type_by_name('test-Type1')
    
    if not symbol.IsActive:
        symbol.Activate()

    for p in points:
        # Place a family instance at the original point
        instance1 = doc.Create.NewFamilyInstance(p, symbol, StructuralType.NonStructural)

        ref = ri.FindNearest(p, direction)
        if ref is not None:
            refel = ref.GetReference()
            link_instance = doc.GetElement(refel.ElementId)
            try:
                elem = link_instance.GetLinkDocument().GetElement(refel.LinkedElementId)
                print(elem.Id)
                refp = ref.GetReference().GlobalPoint

                # Place a family instance at the detected reference point
                instance2 = doc.Create.NewFamilyInstance(refp, symbol, StructuralType.NonStructural)

                height = UnitUtils.ConvertFromInternalUnits(refp.Z, UIunit) - UnitUtils.ConvertFromInternalUnits(p.Z, UIunit)
                heights.append(height)
                print("Element: {}, Height: {}".format(elem.Name, height))
            except:
                pass
        else:
            heights.append(None)
            print("No reference found")

    t.Commit()

print(heights)

Hi @AlexanderVandenbergh have you tried at pyrevit forum ?

i’ll post it there too :slight_smile:

1 Like

Yeah think you have better luck there :wink:

1 Like