Find Intersecting Rooms and Areas

# -*- coding: utf-8 -*-
__title__   = "Find Intersecting Rooms&Areas"
__doc__ = """Date    = 18.04.2024
__________________________
Description:
Find Intersecting Rooms&Areas and write Area.Name to Room.Name 
(Adjust to your own needs)
_____________________________________________________________________
How-To:
- Run the Tool
- Select AreaScheme of desired Areas
_____________________________________________________________________
Author: Erik Frits"""

# ╦╔╦╗╔═╗╔═╗╦═╗╔╦╗╔═╗
# ║║║║╠═╝║ ║╠╦╝ ║ ╚═╗
# ╩╩ ╩╩  ╚═╝╩╚═ ╩ ╚═╝ IMPORTS
#==================================================
from Autodesk.Revit.DB import *
from Autodesk.Revit.DB.Architecture import Room
from pyrevit import forms

# ╦  ╦╔═╗╦═╗╦╔═╗╔╗ ╦  ╔═╗╔═╗
# ╚╗╔╝╠═╣╠╦╝║╠═╣╠╩╗║  ║╣ ╚═╗
#  ╚╝ ╩ ╩╩╚═╩╩ ╩╚═╝╩═╝╚═╝╚═╝
#==================================================
uidoc = __revit__.ActiveUIDocument
doc   = __revit__.ActiveUIDocument.Document


# ╔═╗╦ ╦╔╗╔╔═╗╔╦╗╦╔═╗╔╗╔╔═╗
# ╠╣ ║ ║║║║║   ║ ║║ ║║║║╚═╗
# ╚  ╚═╝╝╚╝╚═╝ ╩ ╩╚═╝╝╚╝╚═╝
#_____________________________________________________________________
# 📦 Function to create a solid from an Area
def create_area_solid(area):
    area_boundary = area.GetBoundarySegments(SpatialElementBoundaryOptions())

    if area_boundary:
        if len(area_boundary) == 0:
            return None

        profile = CurveLoop()
        for curve in area_boundary[0]:  # First loop is the outer boundary
            profile.Append(curve.GetCurve())

        extrusion_height = 10.0  # ⚠️ Random Height in Feet! ~3m
        return GeometryCreationUtilities.CreateExtrusionGeometry([profile], XYZ.BasisZ, extrusion_height)


#✂️ Function to check if point is inside a solid
def is_point_inside_solid(point, solid):
    # Create a tiny line from Point
    line = Line.CreateBound(point, XYZ(point.X, point.Y, point.Z + 0.01))  # Create Tiny Line
    tolerance = 0.00001

    # Create Intersection Options
    opts = SolidCurveIntersectionOptions()
    opts.ResultType = SolidCurveIntersectionMode.CurveSegmentsInside

    # Intersect Line with Geometry
    sci = solid.IntersectWithCurve(line, opts)

    for i,x in enumerate(sci):
        curve = sci.GetCurveSegment(i)
        pt_start = curve.GetEndPoint(0)
        pt_end   = curve.GetEndPoint(1)

        if point.IsAlmostEqualTo(pt_start, tolerance) or point.IsAlmostEqualTo(pt_end, tolerance):
            return True


# ╔╦╗╔═╗╦╔╗╔
# ║║║╠═╣║║║║
# ╩ ╩╩ ╩╩╝╚╝
#_____________________________________________________________________
from collections import defaultdict

#👉 Get Rooms & Areas
rooms     = FilteredElementCollector(doc).OfCategory(BuiltInCategory.OST_Rooms).WhereElementIsNotElementType().ToElements()
all_areas = FilteredElementCollector(doc).OfCategory(BuiltInCategory.OST_Areas).WhereElementIsNotElementType().ToElements()

#🔎 Sort Areas by AreaScheme
dict_areas = defaultdict(list) # List will be default value for new keys!
for area in all_areas:
    dict_areas[area.AreaScheme.Name].append(area)

#_____________________________________________________________________
from pyrevit import forms

# 👉 Select AreaScheme
sel_area_scheme = forms.SelectFromList.show(dict_areas.keys(), button_name='Select AreaScheme')
if not sel_area_scheme:
    forms.alert('No AreaScheme was selected. Please Try Again')

areas = dict_areas[sel_area_scheme]

#_____________________________________________________________________
#🔓 Start transaction to modify the document
t = Transaction(doc, "Update Rooms")
t.Start()

for area in areas:
    try:
        area_solid = create_area_solid(area)
        if area_solid:
            for room in rooms:
                room_point = room.Location.Point
                if is_point_inside_solid(room_point, area_solid):
                    room.Name = Element.Name.GetValue(area) #Abstract Example

                    #👇 Write something to a Parameter...
                    # value = area.Name
                    # room.LookupParameter("SharedParamName").Set(value)

    except:
        # ⚠️ Print Error Message if Fails
        import traceback
        print(traceback.format_exc())

t.Commit() #🔒

⌨️ Happy Coding!
Erik Frits