Having a problem creating room tags from Linked model

Having a problem creating room tags from Linked model

sgermanoZ2Y2F
Enthusiast Enthusiast
2,919 Views
15 Replies
Message 1 of 16

Having a problem creating room tags from Linked model

sgermanoZ2Y2F
Enthusiast
Enthusiast

Hi all! Thanks in advance for any help you can provide as I'm stuck on getting the tags to show. I've got this working in Dynamo and I'm not sure why I'm having an issue here in c#:

 

  [Transaction(TransactionMode.Manual)]
    public class Command : IExternalCommand
    {
        //private IList<ElementId> roomids = new IList(ElementId);

        public List<ElementId> roomids = new List<ElementId>();
        //public List<LinkElementId> roomLids = new List<LinkElementId>();
        public ElementId linkDocId = new ElementId(BuiltInCategory.OST_RvtLinks);
        //public FamilySymbol tagType = new FamilySymbol();

        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;

            Transaction trans = new Transaction(doc);
            trans.Start("Create Room Tags");

            Document linkDoc = GetLinkRoomElementIds(uiapp, doc);
            TaskDialog.Show("ROOM COUNT", roomids.Count().ToString());
            View v = doc.ActiveView as View;

            //CreateRoomTags(linkDoc, v);
            CreateRoomTags(linkDoc, doc, v);
            doc.Regenerate();
            trans.Commit();
            return Result.Succeeded;
        }

        private void CreateRoomTags(Document link, Document doc, View v)
        {
            for (int i = 0; i < roomids.Count; i++)
            {
                ElementId roomid = roomids[i];
                LinkElementId roomLids = new LinkElementId(roomid);
                Element e = link.GetElement(roomid);
                Room r = e as Room;
                
                if (r != null)
                {
                    XYZ cen = GetRoomCenter(r);
                    if (cen != null)
                    {
                        UV center = new UV(cen.X, cen.Y);
                        var roomTag = doc.Create.NewRoomTag(roomLids,
                            center,
                            v.Id);
                        
                        roomTag.ChangeTypeId(MSARoomTagID(roomTag, doc));
                        
                    }
                    else i++;
                }
                else i++;
                
                //RoomTag roomTag = doc.Create.NewRoomTag(new LinkElementId(linkDocId, roomid),
                //    center,
                //    v.Id);
                //roomTag.RoomTagType(tagType);

            }
        }
        public ElementId MSARoomTagID(RoomTag tag, Document doc)
        {
            string newTagTypeName = "Room Tag";
            string newTagFamilyName = "MSA-G-Room Tag";
            ElementId newTagTypeId = null;
            foreach (ElementId id in tag.GetValidTypes())
            {
                RoomTagType type = doc.GetElement(id) as RoomTagType;
                if (type.Name.Equals(newTagTypeName) &&
                    type.FamilyName.Equals(newTagFamilyName))
                {
                    newTagTypeId = id;
                    return newTagTypeId;
                }
            }
            return null;
        }

        public XYZ GetRoomCenter(Room room)
        {
            // Get the room center point.
            XYZ boundCenter = GetElementCenter(room);
            if (boundCenter != null)
            {
                LocationPoint locPt = (LocationPoint)room.Location;
                XYZ roomCenter = new XYZ(boundCenter.X, boundCenter.Y, locPt.Point.Z);
                return roomCenter;
            }
            return null;
        }
        public XYZ GetElementCenter(Element elem)
        {
            if (elem != null)
            {
                BoundingBoxXYZ bounding = elem.get_BoundingBox(null);
                try
                {
                    XYZ center = (bounding.Max + bounding.Min) * 0.5;
                    return center;
                }
                catch (Exception)
                {
                    return null;
                }
            }
            else return null;
        }
        public Document GetLinkRoomElementIds(UIApplication uiapp, Document doc)
        {
            FilteredElementCollector links = new FilteredElementCollector(doc);
            IList<Element> linkElems = links.OfCategory(BuiltInCategory.OST_RvtLinks).OfClass(typeof(RevitLinkType)).ToElements();

            for (int i = 0; i < linkElems.Count; i++)
            {
                Element e = linkElems[i];
                RevitLinkType linkType = e as RevitLinkType;
                String linkName = String.Concat(linkType.Name.Reverse().Skip(4).Reverse());

                foreach (Document linkedDoc in uiapp.Application.Documents)
                {
                    if (linkedDoc.Title.Equals(linkName))
                    {
                        linkDocId = e.Id;
                        FilteredElementCollector collLinked = new FilteredElementCollector(linkedDoc);
                        IList<Element> linkedRooms = collLinked
                            .OfClass(typeof(SpatialElement)).ToElements();
                        if (linkedRooms != null)
                        {
                            foreach (Element l in linkedRooms)
                            {
                                roomids.Add(l.Id);
                            }
                        }
                        return linkedDoc;
                    }
                }
            }

            return null;

        }       
    }

I'm sure Im missing something obvious here, thanks again!

0 Likes
2,920 Views
15 Replies
Replies (15)
Message 2 of 16

JimJia
Alumni
Alumni

Hi Steve,

Can you help to share more details about the problem you mentioned? it's exception or creation failure?

Besides, can you share your reproducible sample .rvt model because your code use hardcode to find the room tag type.

 


Jim Jia
Autodesk Forge Evangelist
https://forge.autodesk.com
Developer Technical Services
Autodesk Developer Network
Email: Jim.Jia@autodesk.com
Message 3 of 16

sgermanoZ2Y2F
Enthusiast
Enthusiast

Hi Jim,

 

Thanks for your reply. I have provided a link to download a test model with associated links for you to review.

https://drive.google.com/file/d/18eIxP45A4qhn7A-IvUy91hbjbAw8pm3y/view?usp=sharing

Its a simple arch model, and the hard coded tag is already loaded in the model.

 

In regards to the exception, I'm not sure as I'm not getting an exception. which is why I was thinking it is a transaction issue or a regen issue, but I have played with that also with no success. 

0 Likes
Message 4 of 16

sgermanoZ2Y2F
Enthusiast
Enthusiast

Hi Jia - Any feedback on this? Im just circling back around to this app. Could there be a bug in tagging linked rooms via the api perhaps?

0 Likes
Message 5 of 16

Anonymous
Not applicable

After writing and running a macro with the same purpose, I'm finding that the Room Tags are being placed but are not appearing in the view. I'm only able to discern that they're being created because I can select them by ID and then snoop them using RevitLookup. Comparing what I see there to a manually placed tag, I noticed discrepancies between values for the "IsTaggingLink" and "TagText" parameters. For the room tags created by the macro, the "IsTaggingLink" parameter is set to false (whereas for manually placed ones, it's set to true) and the "TagText" parameter is blank (whereas for the manually placed tags, it contains a string representation of the room number and room name). Does this happen to match what others have seen when using the NewRoomTag function? Suggested fixes are greatly appreciated.

0 Likes
Message 6 of 16

sgermanoZ2Y2F
Enthusiast
Enthusiast

I did end up getting this to work and also solved the main bug with transform locations being different between the Link and its location in current model. That is why the tags were being created correctly and not throwing an error in the API, they just were not being located in correct location per view thus not appearing.

 

Here is some code on the transform location I used, hope it helps:

private void CreateRoomTags(Document link, Document doc, View v, XYZ transform)
        {
            for (int i = 0; i < roomids.Count; i++)
            {
                ElementId roomid = roomids[i];
                Element e = link.GetElement(roomid);
                Room r = e as Room;


                if (r != null)
                {
                    LocationPoint cen = r.Location as LocationPoint;

                    if (cen != null)
                    {
                        UV center = new UV((cen.Point.X + transform.X), (cen.Point.Y + transform.Y));


                        try
                        {

                            RoomTag roomTag = doc.Create.NewRoomTag(new LinkElementId(linkDocId, roomid),
                                center,
                                v.Id);
                         

                        }
                        catch (Exception exception)
                        {
                            Console.WriteLine(exception);
                            throw;
                        }

                    }
                    else i++;
                }
                else i++;
               
            }
Message 7 of 16

jeremytammik
Autodesk
Autodesk

Congratulations on solving this, and thank you very much for sharing the solution!

 



Jeremy Tammik
Developer Technical Services
Autodesk Developer Network, ADN Open
The Building Coder

0 Likes
Message 8 of 16

rvtquestions
Advocate
Advocate

In your CreateRoomTags function, what are you inputting as your XYZ transform?

 

RevitLinkInstance.GetTotalTransform().Origin?

0 Likes
Message 9 of 16

Stephen.J.Germano
Explorer
Explorer

I dont have that codebase anymore, but yes I believe that is how I got the global transform.

0 Likes
Message 10 of 16

onBIM-Consulting
Enthusiast
Enthusiast

Many thanks to your solution. It helps me a lot.

In this code snippet below I show a variation of your code that works too.

I would like to highlight the LinkElementId attribution on line 288

onBIMConsulting_0-1685544495518.png

 

 

 

0 Likes
Message 11 of 16

frankloftus
Contributor
Contributor

"the "IsTaggingLink" parameter is set to false (whereas for manually placed ones, it's set to true) and the "TagText" parameter is blank (whereas for the manually placed tags, it contains a string representation of the room number and room name)."


I had this exact same problem, but I think I figured out why IsTaggingLink returns false. If you create a room tag by passing in the ElementId of a linked room, IsTaggingLink will be set to false:

 

room_tag = doc.Create.NewRoomTag(room.Id, room_location_uv, view.Id)


What you need to do if tagging a linked room is pass in the LinkElementId:

 

room_tag = doc.Create.NewRoomTag(LinkElementId(link_instance.Id, room.Id), room_location_uv, view.Id)


Now, IsTaggingLink returns True, but my problem is that room_tag.Room returns Null. This is strange because room_tag.IsInRoom is returning True.


I don't think this issue is the link transform, because I am handling that in my code. The tags are created in the workset of the correct view, but still the tags don't show. I have even accomplished API creation of RoomTags elsewhere in the code and the tags show up at the correct location there.


To reiterate: Does anybody know what could cause the Room property to return null even when a RoomTag is successfully created?

Message 12 of 16

TripleM-Dev.net
Advisor
Advisor

Hi @frankloftus,

 

From the documentation: Room Property " Remarks
In rare cases, the tag may not be associated to a room. The property will be a null reference ( Nothing in Visual Basic) in these situations."

 

Also see these: TaggedLocalRoomId Property  and for rooms in linked model: TaggedRoomId Property 

Maybe the last one will return a Id for the room in the linked model?

0 Likes
Message 13 of 16

frankloftus
Contributor
Contributor

@TripleM-Dev.net, thank you for responding. I have verified that upon RoomTag creation, the TaggedRoomId is not null. TaggedLocalRoomId is null, as expected when tagging linked rooms. The tag is successfully added to the database, which I know because it is selectable by Id. The newly created tag's Location is also exactly what I set it to upon creation, yet it does not show in the view, even when uncropped.

 

As the documentation states, "In rare cases, the tag may not be associated to a room. The property will be a null reference". I guess I just really need to know what "rare cases" means, and I need to avoid them.

0 Likes
Message 14 of 16

TripleM-Dev.net
Advisor
Advisor

On of the "Rare" cases would be when a room in a link is tagged and that room is later deleted.

Then the room prop and the id would be nothing.

 

But to the issue of creating/visible making of the tag:

- Is it possible the linked model origin doesn't match the current model, so the room centerpoint (for placing the tag) needs a transform (inverted to the link transform) ?

- Tag the room of the link in the UI and the same one in the API, and compare the differences with Revit Lookup (UV coordinates, view ref., location point etc..)

 

0 Likes
Message 15 of 16

frankloftus
Contributor
Contributor

@TripleM-Dev.net 

 

I found my problem. A non-existent LinkElementId for the linked room was being passed in during RoomTag creation. (Specifically, I was passing the incorrect link Id when creating the LinkElementId). This was a result of messy indentation in my function. Totally my fault!

 

Apparently, if you create a non-existent LinkElementId and pass it in to create a RoomTag, no error will be thrown. The RoomTag will simply be added to the database without a room to tag. Thus, it is created in the view's workset, but not visible in any view.

0 Likes
Message 16 of 16

NonicaTeam
Enthusiast
Enthusiast

That was very helpful. Spent hours working on this until I tried this and really helped solved my issue.