Bounding boxes are great, and fast, but having dealt with rotational issues in past now when dealing with spacial relationships between elements which are non-axis aligned I either look to work with one of the following:
- Geometry Solid Intersects. Via OOTB nodes for small cases
or in Python Coding with the BooleanOperationsUtils.ExecuteBooleanOperation(solid, reference, BooleanOperationsType.Intersect) for larger operations - ReferenceIntersector to project rays to find elements in associated proximities directionally.
Here is an example for windows:
import clr,sys,System
# Revit API
clr.AddReference('RevitAPI')
import Autodesk
from Autodesk.Revit.DB import *
# Revit Services for Transactions
clr.AddReference('RevitServices')
import RevitServices
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager
# Document Essentials
doc = DocumentManager.Instance.CurrentDBDocument
uiapp = DocumentManager.Instance.CurrentUIApplication
app = uiapp.Application
uidoc = uiapp.ActiveUIDocument
# Revit Nodes
clr.AddReference("RevitNodes")
import Revit
clr.ImportExtensions(Revit.GeometryConversion)
import sys
import clr
clr.AddReference('ProtoGeometry')
from Autodesk.DesignScript.Geometry import *
left = []
right = []
# Get all windoes and walls in view
walls = FilteredElementCollector(doc,doc.ActiveView.Id).OfCategory(BuiltInCategory.OST_Walls).ToElements()
windows = FilteredElementCollector(doc,doc.ActiveView.Id).OfCategory(BuiltInCategory.OST_Windows).ToElements()
for window in windows:
# Get facing directions
facing = window.FacingOrientation.ToVector()
left_direction = Vector.Rotate(facing,Vector.ByCoordinates(0,0,1),90)
right_direction = Vector.Rotate(facing,Vector.ByCoordinates(0,0,1),-90)
#Get Window location points for left and right sides
location = window.Location.Point.ToPoint()
half_window_width = float(window.Symbol.LookupParameter('Width').AsValueString())/2
left_point = Geometry.Translate(location,left_direction,half_window_width)
right_point = Geometry.Translate(location,right_direction,half_window_width)
# Find elements either side
cat_list = [BuiltInCategory.OST_Walls]
typed_list = System.Collections.Generic.List[BuiltInCategory](cat_list)
cat = ElementMulticategoryFilter(typed_list)
refInter = ReferenceIntersector(cat, FindReferenceTarget.Face, doc.ActiveView)
refInter.FindReferencesInRevitLinks = True
# See whats directly intersecting a ray projected off the side of window
left_check = refInter.Find(left_point.ToXyz(), left_direction.ToXyz())
left_elems = [c.GetReference() for c in left_check]
left_dists = [c.Proximity for c in left_check]
left_refs = [c.ElementId for c in left_elems]
l_index = left_dists.index(min(left_dists))
l_elem = doc.GetElement(left_refs[l_index])
left.append(l_elem)
# See whats directly intersecting a ray projected off the side of window
right_check = refInter.Find(right_point.ToXyz(), right_direction.ToXyz())
right_elems = [c.GetReference() for c in right_check]
right_dists = [c.Proximity for c in right_check]
right_refs = [c.ElementId for c in right_elems]
r_index = right_dists.index(min(right_dists))
r_elem = doc.GetElement(right_refs[r_index])
right.append(r_elem)
OUT = windows,left,right