Anderson
Anderson

Reputation: 5

Revit API C# Script - Placing element at Location point of every room?

I am new to creating C# Add ins for Revit 2022 so apologies if something I say is incorrect.

I wish to place an element (Fire alarm symbol in this scenario) into every room of a house model if the size of the room is a specific size (this will be expanded on later). I currently have code placed that inserts the element into the model based on a a given XYZ value

I wish to use the Location Point of each room instead as it will place the fire alarm into the specific room but I am running into issues with this, the code is unable to use the location Point data.

Here is my code so far

namespace Project
{
    [Transaction(TransactionMode.Manual)]
    [Regeneration(RegenerationOption.Manual)]


    class Class1 : IExternalCommand
    {
        public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
        {
            UIApplication uiapp = commandData.Application;
            UIDocument uidoc = uiapp.ActiveUIDocument;
            Application app = uiapp.Application;
            Document doc = uidoc.Document;

            FilteredElementCollector roomCollector = new FilteredElementCollector(doc).OfClass(typeof(SpatialElement));
            FilteredElementCollector colLevels = new FilteredElementCollector(doc).WhereElementIsNotElementType().OfCategory(BuiltInCategory.INVALID).OfClass(typeof(Level));
            FilteredElementCollector fireAlarm = new FilteredElementCollector(doc).OfClass(typeof(FamilySymbol)).OfCategory(BuiltInCategory.OST_FireAlarmDevices);
            
            //Grab first level
            Level level = colLevels.FirstElement() as Level;


            FamilySymbol firstAlarm = fireAlarm.FirstElement() as FamilySymbol;

            using (Transaction tx = new Transaction(doc))
            {
                try
                {
                    tx.Start("Start");
                    if (!firstAlarm.IsActive)
                    {
                        firstAlarm.Activate();
                    }

                    foreach (SpatialElement oneRoom in roomCollector)
                    {
                        Room room = oneRoom as Room;
                        double area = room.Area;

                        //This should get the location point of a room, then the location point of a new room once the code loops back, but it doesn't seem to do that
                        LocationPoint location = room.Location as LocationPoint;
                        XYZ point = location.Point;


            //XYZ varibale to place the fire alarms in a specific place
                        XYZ origin = new XYZ(15, 0, 0);

                       //Room size
                        double smallRoom = 301;

                        //If the area of the room is smaller than or equal to 301, place the fire alarm symbol/element into that room
                        if (area <= smallRoom)
                        {
                             //This will place the fire alarm symbol onto the model
                             doc.Create.NewFamilyInstance(origin, firstAlarm, level, Autodesk.Revit.DB.Structure.StructuralType.NonStructural);

                             //This will not place the fire alarm symbol onto the model
                             doc.Create.NewFamilyInstance(point, firstAlarm, level, Autodesk.Revit.DB.Structure.StructuralType.NonStructural);
                        }
                    }

                    tx.Commit();
                }
                catch (Exception e)
                {
                    Debug.Print(e.Message);
                    tx.RollBack();
                }
            }
            
            return Result.Succeeded;
        }
    }
}

So the ideal scenario for the code is:

Get the area and location point values of the first room

If the rooms area is smaller or equal to 301, place one fire alarm symbol where the location point is for that specific room

Repeat for room 2, 3 etc

I will keep working at this in the meantime but any help on this is greatly appreciated EDIT I solved the issue by changing the location point code (below double area = room.Area;) to this:

Location loc = room.Location;

LocationPoint location = loc as LocationPoint;

XYZ point = (null == location) ? XYZ.Zero : location.Point;

This solved the first issue i ran into

Upvotes: 0

Views: 2062

Answers (1)

Jeremy Tammik
Jeremy Tammik

Reputation: 8294

Your approach sounds fine to me, in principle.

What problem are you facing? You don't mention.

Possibly, some rooms are unplaced and have no location point.

Furthermore, a room has no geometry per se, so the Element Location property may not be populated at all for rooms.

Are you aware of RevitLookup? That is the tool of choice to explore the Revit database, its elements, their properties and relationships. That will enable you to interactively explore the values of the location property, the relationship to the room tag, the room boundary, etc.

Are you aware of the standard approach to address a Revit API programming task?

Various other possibilities to determine suitable placement points for fire alarms are also feasible, e.g.:

  • Use the location point of the room tag associated with the room
  • Determine the room boundary and implement an algorithm to determine your desired location point or points within it.

Upvotes: 1

Related Questions