Room to Space Script

Hello,
I’m working on a script to transform all room existing in a linked file to spaces for MEP use.
It will be helpfull, if somebody can point me to a such script or something like already done.

If not can someone help me by telling me the easiest way to achieve this script?
Thank you in advance

Blockquote

This sounds like a great script idea! Have you tried asking ChatGPT about it? If you do, just be sure to say “in python using the Revit API” to clue ChatGPT into what you’re working with. It usually has really good suggestions.

Thank you for the reply and Happy new year.
I tried some AI like GPT, Bard and Codeium. Thes answers are more or less the same, but they point me to wrong classes or methodes. here an example from Bard:

import clr
clr.AddReference('RevitAPI')
from Autodesk.Revit.DB import *

# Get the current document and active view
doc = __revit__.ActiveUIDocument.Document
view = doc.ActiveView

# Get the linked model
linked_models = FilteredElementCollector(doc).OfClass(RevitLinkInstance).ToElements()
linked_model = linked_models[0]  # Assuming you want to work with the first linked model

# Access elements in the linked model
link_doc = linked_model.GetLinkDocument()

# Get rooms from the linked model
rooms = FilteredElementCollector(link_doc).OfCategory(BuiltInCategory.OST_Rooms).WhereElementIsNotElementType().ToElements()

# Create corresponding spaces in the current document
for room in rooms:
    # Map room properties to space properties as needed
    space = Space.Create(doc, room.Location.Point, room.LevelId)
    space.Name = room.Name
    # ... Add more property mappings as needed ...

    # Place the space in the same location as the room
    space.Location = room.Location

    # Add the space to the active view
    view.AddElement(space)

But to be honest, it help me, in some way, to structure the workflow to realise the script.

Any further development or insight on this?

A pretty simple script… just write some code.
Get the rooms with a FilteredElementCollector. Ignore rooms not placed (no area).
Iterate over the rooms and use the location point, phase and level to place spaces inside a transaction.
myspace = doc.Create.NewSpace(level, phase, new UV(locationPoint.X, locationPoint.Y))

You can refine the script by checking if there are already spaces so you don’t get duplicates in case this is a second run. And you might want to work with linked files if the rooms are coming from a separate linked Revit file.
Things to watch for are phasing and levels. If they match up - great. If not - you need to map levels and phases from file to file.
You also need to watch geometry translation from file to file if they don’t share the same file coordinate system (best to have that just in case.) Code below doesn’t catch all that, but is a start.

# -*- coding: utf-8 -*-

from pyrevit import revit, DB, forms
from Autodesk.Revit.DB import (
    FilteredElementCollector,
    BuiltInCategory,
    BuiltInParameter,
    RevitLinkInstance,
    Transaction,
    LocationPoint,
    UV
)
from Autodesk.Revit.UI.Selection import ObjectType, ISelectionFilter

doc = revit.doc
uidoc = revit.uidoc


class RevitLinkSelectionFilter(ISelectionFilter):
    def AllowElement(self, elem):
        return isinstance(elem, RevitLinkInstance)

    def AllowReference(self, ref, point):
        return False


def get_param_value(elem, bip):
    p = elem.get_Parameter(bip)
    if p:
        return p.AsString() or ""
    return ""


def find_host_level_by_elevation(z, tolerance=0.5):
    levels = (
        FilteredElementCollector(doc)
        .OfClass(DB.Level)
        .WhereElementIsNotElementType()
        .ToElements()
    )

    closest = None
    closest_delta = None

    for lvl in levels:
        delta = abs(lvl.Elevation - z)
        if closest is None or delta < closest_delta:
            closest = lvl
            closest_delta = delta

    if closest and closest_delta <= tolerance:
        return closest

    return closest


# Select linked model
ref = uidoc.Selection.PickObject(
    ObjectType.Element,
    RevitLinkSelectionFilter(),
    "Select linked model containing Rooms"
)

link_inst = doc.GetElement(ref.ElementId)
link_doc = link_inst.GetLinkDocument()

if not link_doc:
    forms.alert("Could not access linked document.", exitscript=True)

link_transform = link_inst.GetTotalTransform()

rooms = (
    FilteredElementCollector(link_doc)
    .OfCategory(BuiltInCategory.OST_Rooms)
    .WhereElementIsNotElementType()
    .ToElements()
)

created = 0
skipped = []

t = Transaction(doc, "Create Spaces From Linked Rooms")
t.Start()

for room in rooms:
    try:
        if room.Area <= 0:
            skipped.append("{} - no area".format(room.Id))
            continue

        loc = room.Location
        if not isinstance(loc, LocationPoint):
            skipped.append("{} - no location point".format(room.Id))
            continue

        # Transform linked room point into host coordinates
        link_pt = loc.Point
        host_pt = link_transform.OfPoint(link_pt)

        host_level = find_host_level_by_elevation(host_pt.Z)

        if not host_level:
            skipped.append("{} - no matching host level".format(room.Id))
            continue

        space = doc.Create.NewSpace(host_level, UV(host_pt.X, host_pt.Y))

        if not space:
            skipped.append("{} - space not created".format(room.Id))
            continue

        # Copy Room Number
        room_number = room.Number
        try:
            space.Number = room_number
        except:
            p = space.get_Parameter(BuiltInParameter.ROOM_NUMBER)
            if p and not p.IsReadOnly:
                p.Set(room_number)

        # Copy Room Name
        room_name = room.Name
        try:
            space.Name = room_name
        except:
            p = space.get_Parameter(BuiltInParameter.ROOM_NAME)
            if p and not p.IsReadOnly:
                p.Set(room_name)

        created += 1

    except Exception as ex:
        skipped.append("{} - {}".format(room.Id, ex))

t.Commit()

forms.alert(
    "Created {} spaces from linked rooms.\nSkipped {} rooms.".format(
        created,
        len(skipped)
    ),
    title="Spaces From Linked Rooms"
)
1 Like